this repo has no description

Compare changes

Choose any two refs to compare.

Changed files
+5319 -1762
.github
nix
packages
browser
core
core-extensions
injector
node-preload
types
web-preload
scripts
+4 -8
.github/workflows/browser.yml
··· 10 name: Browser extension builds 11 runs-on: ubuntu-latest 12 steps: 13 - - uses: actions/checkout@v3 14 - 15 - - uses: pnpm/action-setup@v2 16 - with: 17 - version: 9 18 - run_install: false 19 - - uses: actions/setup-node@v3 20 with: 21 - node-version: 18 22 cache: pnpm 23 24 - name: Install dependencies
··· 10 name: Browser extension builds 11 runs-on: ubuntu-latest 12 steps: 13 + - uses: actions/checkout@v4 14 + - uses: pnpm/action-setup@v4 15 + - uses: actions/setup-node@v4 16 with: 17 + node-version: 22 18 cache: pnpm 19 20 - name: Install dependencies
+4 -8
.github/workflows/lint.yml
··· 9 name: Lint commits 10 runs-on: ubuntu-latest 11 steps: 12 - - uses: actions/checkout@v3 13 - 14 - - uses: pnpm/action-setup@v2 15 - with: 16 - version: 9 17 - run_install: false 18 - - uses: actions/setup-node@v3 19 with: 20 - node-version: 18 21 cache: pnpm 22 23 - name: Install dependencies
··· 9 name: Lint commits 10 runs-on: ubuntu-latest 11 steps: 12 + - uses: actions/checkout@v4 13 + - uses: pnpm/action-setup@v4 14 + - uses: actions/setup-node@v4 15 with: 16 + node-version: 22 17 cache: pnpm 18 19 - name: Install dependencies
+4 -8
.github/workflows/nightly.yml
··· 15 name: Nightly builds on GitHub Pages 16 runs-on: ubuntu-latest 17 steps: 18 - - uses: actions/checkout@v3 19 - 20 - - uses: pnpm/action-setup@v2 21 - with: 22 - version: 9 23 - run_install: false 24 - - uses: actions/setup-node@v3 25 with: 26 - node-version: 18 27 cache: pnpm 28 29 - name: Install dependencies
··· 15 name: Nightly builds on GitHub Pages 16 runs-on: ubuntu-latest 17 steps: 18 + - uses: actions/checkout@v4 19 + - uses: pnpm/action-setup@v4 20 + - uses: actions/setup-node@v4 21 with: 22 + node-version: 22 23 cache: pnpm 24 25 - name: Install dependencies
+16
.github/workflows/nix.yml
···
··· 1 + name: Check Nix flake 2 + on: [push, pull_request] 3 + 4 + permissions: 5 + checks: write 6 + 7 + jobs: 8 + nix: 9 + name: Check Nix flake 10 + runs-on: ubuntu-latest 11 + steps: 12 + - uses: actions/checkout@v4 13 + - uses: DeterminateSystems/nix-installer-action@main 14 + 15 + - name: Build default flake output 16 + run: nix build
+4 -8
.github/workflows/release.yml
··· 13 name: Release builds to GitHub Releases 14 runs-on: ubuntu-latest 15 steps: 16 - - uses: actions/checkout@v3 17 - 18 - - uses: pnpm/action-setup@v2 19 - with: 20 - version: 9 21 - run_install: false 22 - - uses: actions/setup-node@v3 23 with: 24 - node-version: 18 25 cache: pnpm 26 27 - name: Install dependencies
··· 13 name: Release builds to GitHub Releases 14 runs-on: ubuntu-latest 15 steps: 16 + - uses: actions/checkout@v4 17 + - uses: pnpm/action-setup@v4 18 + - uses: actions/setup-node@v4 19 with: 20 + node-version: 22 21 cache: pnpm 22 23 - name: Install dependencies
+5 -11
.github/workflows/types.yml
··· 11 name: Publish types on npm 12 runs-on: ubuntu-latest 13 steps: 14 - - uses: actions/checkout@v3 15 - 16 - - uses: pnpm/action-setup@v2 17 - with: 18 - version: 9 19 - run_install: false 20 - - uses: actions/setup-node@v3 21 with: 22 - node-version: 18 23 cache: pnpm 24 registry-url: https://registry.npmjs.org 25 ··· 31 run: pnpm run build 32 33 - name: Publish types 34 - run: | 35 - cd packages/types 36 - pnpm publish --access public --no-git-checks 37 env: 38 NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
··· 11 name: Publish types on npm 12 runs-on: ubuntu-latest 13 steps: 14 + - uses: actions/checkout@v4 15 + - uses: pnpm/action-setup@v4 16 + - uses: actions/setup-node@v4 17 with: 18 + node-version: 22 19 cache: pnpm 20 registry-url: https://registry.npmjs.org 21 ··· 27 run: pnpm run build 28 29 - name: Publish types 30 + run: pnpm publish --filter=./packages/types --access public --no-git-checks 31 env: 32 NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+1 -1
.gitignore
··· 3 dist.tar.gz 4 .DS_Store 5 eslint_report.json 6 - 7 # Nix 8 /result 9 *.drv
··· 3 dist.tar.gz 4 .DS_Store 5 eslint_report.json 6 + .eslintcache 7 # Nix 8 /result 9 *.drv
+4 -4
.prettierrc
··· 1 { 2 - "printWidth": 120, 3 - "trailingComma": "none", 4 - "tabWidth": 2, 5 - "singleQuote": false 6 }
··· 1 { 2 + "printWidth": 120, 3 + "trailingComma": "none", 4 + "tabWidth": 2, 5 + "singleQuote": false 6 }
+4 -3
CHANGELOG.md
··· 1 - - Fixed missing restart prompt when updating an extension 2 - - Updated the Context Menu API to support regex 3 - - Moved Moonbase to use a different API to hopefully fix a rare crash
··· 1 + ## Core 2 + 3 + - Updated mappings 4 + - Fixed using remapped paths as patch finds not working
+1 -1
README.md
··· 23 24 moonlight is heavily inspired by hh3 (a private client mod) and the projects before it that it is inspired by, namely EndPwn. All core code is original or used with permission from their respective authors where not copyleft. 25 26 - **_This is an experimental passion project._** Anything and everything is subject to change, but it is stable enough for tinkerers and developers to experiment with. 27 28 moonlight is licensed under the [GNU Lesser General Public License](https://www.gnu.org/licenses/lgpl-3.0.html) (`LGPL-3.0-or-later`). See [the documentation](https://moonlight-mod.github.io/) for more information.
··· 23 24 moonlight is heavily inspired by hh3 (a private client mod) and the projects before it that it is inspired by, namely EndPwn. All core code is original or used with permission from their respective authors where not copyleft. 25 26 + moonlight is a **_passion project_** - things may break from time to time, but we try our best to keep things working in a timely manner. 27 28 moonlight is licensed under the [GNU Lesser General Public License](https://www.gnu.org/licenses/lgpl-3.0.html) (`LGPL-3.0-or-later`). See [the documentation](https://moonlight-mod.github.io/) for more information.
+4 -73
flake.lock
··· 18 "type": "github" 19 } 20 }, 21 - "flake-utils_2": { 22 - "inputs": { 23 - "systems": "systems_2" 24 - }, 25 - "locked": { 26 - "lastModified": 1701680307, 27 - "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", 28 - "owner": "numtide", 29 - "repo": "flake-utils", 30 - "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", 31 - "type": "github" 32 - }, 33 - "original": { 34 - "owner": "numtide", 35 - "repo": "flake-utils", 36 - "type": "github" 37 - } 38 - }, 39 "nixpkgs": { 40 "locked": { 41 - "lastModified": 1728067476, 42 - "narHash": "sha256-/uJcVXuBt+VFCPQIX+4YnYrHaubJSx4HoNsJVNRgANM=", 43 "owner": "NixOS", 44 "repo": "nixpkgs", 45 - "rev": "6e6b3dd395c3b1eb9be9f2d096383a8d05add030", 46 "type": "github" 47 }, 48 "original": { 49 "owner": "NixOS", 50 - "ref": "nixos-24.05", 51 - "repo": "nixpkgs", 52 - "type": "github" 53 - } 54 - }, 55 - "nixpkgs_2": { 56 - "locked": { 57 - "lastModified": 1736344531, 58 - "narHash": "sha256-8YVQ9ZbSfuUk2bUf2KRj60NRraLPKPS0Q4QFTbc+c2c=", 59 - "owner": "nixos", 60 - "repo": "nixpkgs", 61 - "rev": "bffc22eb12172e6db3c5dde9e3e5628f8e3e7912", 62 - "type": "github" 63 - }, 64 - "original": { 65 - "owner": "nixos", 66 "ref": "nixos-unstable", 67 "repo": "nixpkgs", 68 "type": "github" 69 } 70 }, 71 - "pnpm2nix": { 72 - "inputs": { 73 - "flake-utils": "flake-utils_2", 74 - "nixpkgs": "nixpkgs_2" 75 - }, 76 - "locked": { 77 - "lastModified": 1736457458, 78 - "narHash": "sha256-eiw+hAsxavEgBfhwrktNI2hwvgeVDzBDYClx/yqka78=", 79 - "owner": "NotNite", 80 - "repo": "pnpm2nix-nzbr", 81 - "rev": "4ac61c6a50623da937dca005e3dbcb8862aafb83", 82 - "type": "github" 83 - }, 84 - "original": { 85 - "owner": "NotNite", 86 - "repo": "pnpm2nix-nzbr", 87 - "type": "github" 88 - } 89 - }, 90 "root": { 91 "inputs": { 92 "flake-utils": "flake-utils", 93 - "nixpkgs": "nixpkgs", 94 - "pnpm2nix": "pnpm2nix" 95 } 96 }, 97 "systems": { 98 - "locked": { 99 - "lastModified": 1681028828, 100 - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 101 - "owner": "nix-systems", 102 - "repo": "default", 103 - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 104 - "type": "github" 105 - }, 106 - "original": { 107 - "owner": "nix-systems", 108 - "repo": "default", 109 - "type": "github" 110 - } 111 - }, 112 - "systems_2": { 113 "locked": { 114 "lastModified": 1681028828, 115 "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
··· 18 "type": "github" 19 } 20 }, 21 "nixpkgs": { 22 "locked": { 23 + "lastModified": 1744232761, 24 + "narHash": "sha256-gbl9hE39nQRpZaLjhWKmEu5ejtQsgI5TWYrIVVJn30U=", 25 "owner": "NixOS", 26 "repo": "nixpkgs", 27 + "rev": "f675531bc7e6657c10a18b565cfebd8aa9e24c14", 28 "type": "github" 29 }, 30 "original": { 31 "owner": "NixOS", 32 "ref": "nixos-unstable", 33 "repo": "nixpkgs", 34 "type": "github" 35 } 36 }, 37 "root": { 38 "inputs": { 39 "flake-utils": "flake-utils", 40 + "nixpkgs": "nixpkgs" 41 } 42 }, 43 "systems": { 44 "locked": { 45 "lastModified": 1681028828, 46 "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+3 -4
flake.nix
··· 2 description = "Yet another Discord mod"; 3 4 inputs = { 5 - nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; 6 flake-utils.url = "github:numtide/flake-utils"; 7 - pnpm2nix.url = "github:NotNite/pnpm2nix-nzbr"; 8 }; 9 10 - outputs = { self, nixpkgs, flake-utils, pnpm2nix }: 11 - let overlay = import ./nix/overlay.nix { inherit pnpm2nix; }; 12 in flake-utils.lib.eachDefaultSystem (system: 13 let 14 pkgs = import nixpkgs {
··· 2 description = "Yet another Discord mod"; 3 4 inputs = { 5 + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 flake-utils.url = "github:numtide/flake-utils"; 7 }; 8 9 + outputs = { self, nixpkgs, flake-utils }: 10 + let overlay = import ./nix/overlay.nix { }; 11 in flake-utils.lib.eachDefaultSystem (system: 12 let 13 pkgs = import nixpkgs {
+46 -17
nix/default.nix
··· 1 - { pkgs, mkPnpmPackage }: 2 3 - mkPnpmPackage rec { 4 - workspace = ./..; 5 src = ./..; 6 7 - # Work around a bug with how it expects dist 8 - components = [ 9 - "packages/core" 10 - "packages/core-extensions" 11 - "packages/injector" 12 - "packages/node-preload" 13 - "packages/types" 14 - "packages/web-preload" 15 ]; 16 - distDirs = [ "dist" ]; 17 18 - copyNodeModules = true; 19 - buildPhase = "pnpm run build"; 20 - installPhase = "cp -r dist $out"; 21 22 - meta = with pkgs.lib; { 23 description = "Yet another Discord mod"; 24 homepage = "https://moonlight-mod.github.io/"; 25 license = licenses.lgpl3; 26 maintainers = with maintainers; [ notnite ]; 27 }; 28 - }
··· 1 + { 2 + lib, 3 + stdenv, 4 + nodejs_22, 5 + pnpm_10, 6 + }: 7 8 + stdenv.mkDerivation (finalAttrs: { 9 + pname = "moonlight"; 10 + version = (builtins.fromJSON (builtins.readFile ./../package.json)).version; 11 + 12 src = ./..; 13 14 + outputs = [ "out" "firefox" ]; 15 + 16 + nativeBuildInputs = [ 17 + nodejs_22 18 + pnpm_10.configHook 19 ]; 20 + 21 + pnpmDeps = pnpm_10.fetchDeps { 22 + inherit (finalAttrs) pname version src; 23 + hash = "sha256-I+zRCUqJabpGJRFBGW0NrM9xzyzeCjioF54zlCpynBU="; 24 + }; 25 + 26 + env = { 27 + NODE_ENV = "production"; 28 + MOONLIGHT_VERSION = "v${finalAttrs.version}"; 29 + }; 30 + 31 + buildPhase = '' 32 + runHook preBuild 33 + 34 + pnpm run build 35 + pnpm run browser-mv2 36 + 37 + runHook postBuild 38 + ''; 39 + 40 + installPhase = '' 41 + runHook preInstall 42 43 + cp -r dist $out 44 + 45 + mkdir -p $firefox/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/ 46 + mv $out/browser-mv2 $firefox/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/{0fb6d66f-f22d-4555-a87b-34ef4bea5e2a} 47 + 48 + runHook postInstall 49 + ''; 50 51 + meta = with lib; { 52 description = "Yet another Discord mod"; 53 homepage = "https://moonlight-mod.github.io/"; 54 license = licenses.lgpl3; 55 maintainers = with maintainers; [ notnite ]; 56 }; 57 + })
+3 -6
nix/overlay.nix
··· 1 - { pnpm2nix }: 2 3 let 4 nameTable = { ··· 29 ''; 30 31 packageJson = '' 32 - {"name":"discord","main":"./injector.js","private":true} 33 ''; 34 35 in old.installPhase + "\n" + '' ··· 49 ''; 50 }); 51 in final: prev: rec { 52 - moonlight-mod = final.callPackage ./default.nix { 53 - pkgs = final; 54 - mkPnpmPackage = pnpm2nix.packages.${final.system}.mkPnpmPackage; 55 - }; 56 discord = mkOverride prev moonlight-mod "discord"; 57 discord-ptb = mkOverride prev moonlight-mod "discord-ptb"; 58 discord-canary = mkOverride prev moonlight-mod "discord-canary";
··· 1 + { ... }: 2 3 let 4 nameTable = { ··· 29 ''; 30 31 packageJson = '' 32 + {"name":"${name}","main":"./injector.js","private":true} 33 ''; 34 35 in old.installPhase + "\n" + '' ··· 49 ''; 50 }); 51 in final: prev: rec { 52 + moonlight-mod = final.callPackage ./default.nix { }; 53 discord = mkOverride prev moonlight-mod "discord"; 54 discord-ptb = mkOverride prev moonlight-mod "discord-ptb"; 55 discord-canary = mkOverride prev moonlight-mod "discord-canary";
+23 -12
package.json
··· 1 { 2 "name": "moonlight", 3 - "version": "1.3.1", 4 "description": "Yet another Discord mod", 5 - "homepage": "https://moonlight-mod.github.io/", 6 "license": "LGPL-3.0-or-later", 7 "repository": { 8 "type": "git", 9 "url": "git+https://github.com/moonlight-mod/moonlight.git" ··· 11 "bugs": { 12 "url": "https://github.com/moonlight-mod/moonlight/issues" 13 }, 14 "scripts": { 15 "build": "node build.mjs", 16 "dev": "node build.mjs --watch", ··· 18 "browser": "node build.mjs --browser", 19 "browser-mv2": "node build.mjs --browser --mv2", 20 "lint": "eslint packages", 21 - "lint:fix": "eslint packages --fix", 22 - "lint:report": "eslint --output-file eslint_report.json --format json packages", 23 "typecheck": "tsc --noEmit", 24 "check": "pnpm run lint && pnpm run typecheck", 25 - "prepare": "husky install" 26 }, 27 "devDependencies": { 28 - "esbuild": "^0.19.3", 29 - "esbuild-copy-static-files": "^0.1.0", 30 - "eslint": "^9.12.0", 31 - "@moonlight-mod/eslint-config": "github:moonlight-mod/eslint-config", 32 - "husky": "^8.0.3", 33 - "prettier": "^3.1.0", 34 - "typescript": "^5.3.2" 35 } 36 }
··· 1 { 2 "name": "moonlight", 3 + "version": "1.3.14", 4 + "packageManager": "pnpm@10.7.1", 5 "description": "Yet another Discord mod", 6 "license": "LGPL-3.0-or-later", 7 + "homepage": "https://moonlight-mod.github.io/", 8 "repository": { 9 "type": "git", 10 "url": "git+https://github.com/moonlight-mod/moonlight.git" ··· 12 "bugs": { 13 "url": "https://github.com/moonlight-mod/moonlight/issues" 14 }, 15 + "engineStrict": true, 16 + "engines": { 17 + "node": ">=22", 18 + "pnpm": ">=10", 19 + "npm": "pnpm", 20 + "yarn": "pnpm" 21 + }, 22 "scripts": { 23 "build": "node build.mjs", 24 "dev": "node build.mjs --watch", ··· 26 "browser": "node build.mjs --browser", 27 "browser-mv2": "node build.mjs --browser --mv2", 28 "lint": "eslint packages", 29 + "lint:fix": "pnpm lint --fix", 30 + "lint:report": "pnpm lint --output-file eslint_report.json --format json", 31 "typecheck": "tsc --noEmit", 32 "check": "pnpm run lint && pnpm run typecheck", 33 + "prepare": "husky install", 34 + "updates": "pnpm taze -r" 35 }, 36 "devDependencies": { 37 + "@moonlight-mod/eslint-config": "catalog:dev", 38 + "@types/node": "catalog:dev", 39 + "esbuild": "catalog:dev", 40 + "esbuild-copy-static-files": "catalog:dev", 41 + "eslint": "catalog:dev", 42 + "husky": "catalog:dev", 43 + "prettier": "catalog:dev", 44 + "taze": "catalog:dev", 45 + "typescript": "catalog:dev" 46 } 47 }
+2 -1
packages/browser/blockLoading.json
··· 6 "type": "block" 7 }, 8 "condition": { 9 - "urlFilter": "*://discord.com/assets/*.js", 10 "resourceTypes": ["script"] 11 } 12 }
··· 6 "type": "block" 7 }, 8 "condition": { 9 + "requestDomains": ["discord.com", "discordapp.com"], 10 + "urlFilter": "*/assets/*.js", 11 "resourceTypes": ["script"] 12 } 13 }
+10 -4
packages/browser/manifest.json
··· 1 { 2 "manifest_version": 3, 3 "name": "moonlight", 4 "description": "Yet another Discord mod", 5 - "version": "1.3.1", 6 "permissions": ["declarativeNetRequestWithHostAccess", "webRequest", "scripting", "webNavigation"], 7 - "host_permissions": ["https://moonlight-mod.github.io/*", "https://api.github.com/*", "https://*.discord.com/*"], 8 "content_scripts": [ 9 { 10 "js": ["index.js"], 11 - "matches": ["https://*.discord.com/*"], 12 "run_at": "document_start", 13 "world": "MAIN" 14 } ··· 34 "web_accessible_resources": [ 35 { 36 "resources": ["index.js"], 37 - "matches": ["https://*.discord.com/*"] 38 } 39 ] 40 }
··· 1 { 2 + "$schema": "https://json.schemastore.org/chrome-manifest", 3 "manifest_version": 3, 4 "name": "moonlight", 5 "description": "Yet another Discord mod", 6 + "version": "1.3.14", 7 "permissions": ["declarativeNetRequestWithHostAccess", "webRequest", "scripting", "webNavigation"], 8 + "host_permissions": [ 9 + "https://moonlight-mod.github.io/*", 10 + "https://api.github.com/*", 11 + "https://*.discord.com/*", 12 + "https://*.discordapp.com/*" 13 + ], 14 "content_scripts": [ 15 { 16 "js": ["index.js"], 17 + "matches": ["https://*.discord.com/*", "https://*.discordapp.com/*"], 18 "run_at": "document_start", 19 "world": "MAIN" 20 } ··· 40 "web_accessible_resources": [ 41 { 42 "resources": ["index.js"], 43 + "matches": ["https://*.discord.com/*", "https://*.discordapp.com/*"] 44 } 45 ] 46 }
+12 -6
packages/browser/manifestv2.json
··· 1 { 2 "manifest_version": 2, 3 "name": "moonlight", 4 "description": "Yet another Discord mod", 5 - "version": "1.3.1", 6 "permissions": [ 7 "webRequest", 8 "webRequestBlocking", 9 "scripting", 10 "webNavigation", 11 - "https://*.discord.com/assets/*.js", 12 "https://moonlight-mod.github.io/*", 13 - "https://api.github.com/*", 14 - "https://*.discord.com/*" 15 ], 16 "background": { 17 "scripts": ["background.js"] ··· 19 "content_scripts": [ 20 { 21 "js": ["index.js"], 22 - "matches": ["https://*.discord.com/*"], 23 "run_at": "document_start", 24 "world": "MAIN" 25 } 26 - ] 27 }
··· 1 { 2 + "$schema": "https://json.schemastore.org/chrome-manifest", 3 "manifest_version": 2, 4 "name": "moonlight", 5 "description": "Yet another Discord mod", 6 + "version": "1.3.14", 7 "permissions": [ 8 "webRequest", 9 "webRequestBlocking", 10 "scripting", 11 "webNavigation", 12 + "https://*.discord.com/*", 13 + "https://*.discordapp.com/*", 14 "https://moonlight-mod.github.io/*", 15 + "https://api.github.com/*" 16 ], 17 "background": { 18 "scripts": ["background.js"] ··· 20 "content_scripts": [ 21 { 22 "js": ["index.js"], 23 + "matches": ["https://*.discord.com/*", "https://*.discordapp.com/*"], 24 "run_at": "document_start", 25 "world": "MAIN" 26 } 27 + ], 28 + "browser_specific_settings": { 29 + "gecko": { 30 + "id": "{0fb6d66f-f22d-4555-a87b-34ef4bea5e2a}" 31 + } 32 + } 33 }
+12 -2
packages/browser/package.json
··· 1 { 2 "name": "@moonlight-mod/browser", 3 "private": true, 4 "dependencies": { 5 "@moonlight-mod/core": "workspace:*", 6 "@moonlight-mod/types": "workspace:*", 7 "@moonlight-mod/web-preload": "workspace:*", 8 - "@zenfs/core": "^1.0.2", 9 - "@zenfs/dom": "^0.2.16" 10 } 11 }
··· 1 { 2 "name": "@moonlight-mod/browser", 3 "private": true, 4 + "engines": { 5 + "node": ">=22", 6 + "pnpm": ">=10", 7 + "npm": "pnpm", 8 + "yarn": "pnpm" 9 + }, 10 "dependencies": { 11 "@moonlight-mod/core": "workspace:*", 12 "@moonlight-mod/types": "workspace:*", 13 "@moonlight-mod/web-preload": "workspace:*", 14 + "@zenfs/core": "catalog:prod", 15 + "@zenfs/dom": "catalog:prod" 16 + }, 17 + "engineStrict": true, 18 + "devDependencies": { 19 + "@types/chrome": "catalog:dev" 20 } 21 }
+55 -70
packages/browser/src/background-mv2.js
··· 1 /* eslint-disable no-console */ 2 /* eslint-disable no-undef */ 3 4 - const starterUrls = ["web.", "sentry."]; 5 - let blockLoading = true; 6 - let doing = false; 7 - let collectedUrls = new Set(); 8 9 - chrome.webNavigation.onBeforeNavigate.addListener(async (details) => { 10 - const url = new URL(details.url); 11 - if (!blockLoading && url.hostname.endsWith("discord.com")) { 12 - console.log("Blocking", details.url); 13 - blockLoading = true; 14 - collectedUrls.clear(); 15 - } 16 - }); 17 18 - async function doTheThing(urls, tabId) { 19 - console.log("Doing", urls, tabId); 20 21 - blockLoading = false; 22 23 - try { 24 - await chrome.scripting.executeScript({ 25 - target: { tabId }, 26 - world: "MAIN", 27 - args: [urls], 28 - func: async (urls) => { 29 - try { 30 - await window._moonlightBrowserInit(); 31 - } catch (e) { 32 - console.log(e); 33 - } 34 35 - const scripts = [...document.querySelectorAll("script")].filter( 36 - (script) => script.src && urls.some((url) => url.includes(script.src)) 37 - ); 38 39 - // backwards 40 - urls.reverse(); 41 - for (const url of urls) { 42 - const script = scripts.find((script) => url.includes(script.src)); 43 - console.log("adding new script", script); 44 45 - const newScript = document.createElement("script"); 46 - for (const { name, value } of script.attributes) { 47 - newScript.setAttribute(name, value); 48 } 49 - 50 - script.remove(); 51 - document.documentElement.appendChild(newScript); 52 - } 53 - } 54 - }); 55 - } catch (e) { 56 - console.log(e); 57 - } 58 - 59 - doing = false; 60 - collectedUrls.clear(); 61 - } 62 - 63 - chrome.webRequest.onBeforeRequest.addListener( 64 - async (details) => { 65 - if (starterUrls.some((url) => details.url.includes(url))) { 66 - console.log("Adding", details.url); 67 - collectedUrls.add(details.url); 68 } 69 70 - if (collectedUrls.size === starterUrls.length) { 71 - if (doing) return; 72 - if (!blockLoading) return; 73 - doing = true; 74 - const urls = [...collectedUrls]; 75 - const tabId = details.tabId; 76 - 77 - // yes this is a load-bearing sleep 78 - setTimeout(() => doTheThing(urls, tabId), 0); 79 - } 80 - 81 - if (blockLoading) return { cancel: true }; 82 }, 83 { 84 - urls: ["https://*.discord.com/assets/*.js"] 85 }, 86 ["blocking"] 87 ); ··· 94 ) 95 }; 96 }, 97 - { urls: ["https://*.discord.com/*"] }, 98 ["blocking", "responseHeaders"] 99 );
··· 1 /* eslint-disable no-console */ 2 /* eslint-disable no-undef */ 3 4 + const scriptUrls = ["web.", "sentry."]; 5 + let blockedScripts = new Set(); 6 7 + chrome.webRequest.onBeforeRequest.addListener( 8 + async (details) => { 9 + if (details.tabId === -1) return; 10 11 + const url = new URL(details.url); 12 + const hasUrl = scriptUrls.some((scriptUrl) => { 13 + return ( 14 + details.url.includes(scriptUrl) && 15 + !url.searchParams.has("inj") && 16 + (url.host.endsWith("discord.com") || url.host.endsWith("discordapp.com")) 17 + ); 18 + }); 19 + if (hasUrl) blockedScripts.add(details.url); 20 21 + if (blockedScripts.size === scriptUrls.length) { 22 + const blockedScriptsCopy = Array.from(blockedScripts); 23 + blockedScripts.clear(); 24 25 + setTimeout(async () => { 26 + console.log("Starting moonlight"); 27 + await chrome.scripting.executeScript({ 28 + target: { tabId: details.tabId }, 29 + world: "MAIN", 30 + args: [blockedScriptsCopy], 31 + func: async (blockedScripts) => { 32 + console.log("Initializing moonlight"); 33 + try { 34 + await window._moonlightBrowserInit(); 35 + } catch (e) { 36 + console.error(e); 37 + } 38 39 + console.log("Readding scripts"); 40 + try { 41 + const scripts = [...document.querySelectorAll("script")].filter( 42 + (script) => script.src && blockedScripts.some((url) => url.includes(script.src)) 43 + ); 44 45 + blockedScripts.reverse(); 46 + for (const url of blockedScripts) { 47 + if (url.includes("/sentry.")) continue; 48 49 + const script = scripts.find((script) => url.includes(script.src)); 50 + const newScript = document.createElement("script"); 51 + for (const attr of script.attributes) { 52 + if (attr.name === "src") attr.value += "?inj"; 53 + newScript.setAttribute(attr.name, attr.value); 54 + } 55 + script.remove(); 56 + document.documentElement.appendChild(newScript); 57 + } 58 + } catch (e) { 59 + console.error(e); 60 + } 61 } 62 + }); 63 + }, 0); 64 } 65 66 + if (hasUrl) return { cancel: true }; 67 }, 68 { 69 + urls: ["https://*.discord.com/assets/*.js", "https://*.discordapp.com/assets/*.js"] 70 }, 71 ["blocking"] 72 ); ··· 79 ) 80 }; 81 }, 82 + { urls: ["https://*.discord.com/*", "https://*.discordapp.com/*"] }, 83 ["blocking", "responseHeaders"] 84 );
+37 -39
packages/browser/src/background.js
··· 1 /* eslint-disable no-console */ 2 /* eslint-disable no-undef */ 3 4 - const starterUrls = ["web.", "sentry."]; 5 - let blockLoading = true; 6 - let doing = false; 7 - let collectedUrls = new Set(); 8 9 chrome.webNavigation.onBeforeNavigate.addListener(async (details) => { 10 const url = new URL(details.url); 11 - if (!blockLoading && url.hostname.endsWith("discord.com")) { 12 await chrome.declarativeNetRequest.updateEnabledRulesets({ 13 enableRulesetIds: ["modifyResponseHeaders", "blockLoading"] 14 }); 15 - blockLoading = true; 16 - collectedUrls.clear(); 17 } 18 }); 19 20 chrome.webRequest.onBeforeRequest.addListener( 21 async (details) => { 22 if (details.tabId === -1) return; 23 - if (starterUrls.some((url) => details.url.includes(url))) { 24 - console.log("Adding", details.url); 25 - collectedUrls.add(details.url); 26 - } 27 28 - if (collectedUrls.size === starterUrls.length) { 29 - if (doing) return; 30 - if (!blockLoading) return; 31 - doing = true; 32 - const urls = [...collectedUrls]; 33 - console.log("Doing", urls); 34 35 console.log("Running moonlight script"); 36 try { ··· 40 files: ["index.js"] 41 }); 42 } catch (e) { 43 - console.log(e); 44 } 45 46 console.log("Initializing moonlight"); ··· 52 try { 53 await window._moonlightBrowserInit(); 54 } catch (e) { 55 - console.log(e); 56 } 57 } 58 }); ··· 60 console.log(e); 61 } 62 63 - console.log("Updating rulesets"); 64 try { 65 - blockLoading = false; 66 await chrome.declarativeNetRequest.updateEnabledRulesets({ 67 disableRulesetIds: ["blockLoading"], 68 enableRulesetIds: ["modifyResponseHeaders"] 69 }); 70 } catch (e) { 71 - console.log(e); 72 } 73 74 console.log("Readding scripts"); ··· 76 await chrome.scripting.executeScript({ 77 target: { tabId: details.tabId }, 78 world: "MAIN", 79 - args: [urls], 80 - func: async (urls) => { 81 const scripts = [...document.querySelectorAll("script")].filter( 82 - (script) => script.src && urls.some((url) => url.includes(script.src)) 83 ); 84 85 - // backwards 86 - urls.reverse(); 87 - for (const url of urls) { 88 - const script = scripts.find((script) => url.includes(script.src)); 89 - console.log("adding new script", script); 90 91 const newScript = document.createElement("script"); 92 - for (const { name, value } of script.attributes) { 93 - newScript.setAttribute(name, value); 94 } 95 - 96 script.remove(); 97 document.documentElement.appendChild(newScript); 98 } 99 } 100 }); 101 } catch (e) { 102 - console.log(e); 103 } 104 - 105 - console.log("Done"); 106 - doing = false; 107 - collectedUrls.clear(); 108 } 109 }, 110 { 111 - urls: ["*://*.discord.com/assets/*.js"] 112 } 113 );
··· 1 /* eslint-disable no-console */ 2 /* eslint-disable no-undef */ 3 4 + const scriptUrls = ["web.", "sentry."]; 5 + let blockedScripts = new Set(); 6 7 chrome.webNavigation.onBeforeNavigate.addListener(async (details) => { 8 const url = new URL(details.url); 9 + if ( 10 + !url.searchParams.has("inj") && 11 + (url.hostname.endsWith("discord.com") || url.hostname.endsWith("discordapp.com")) 12 + ) { 13 + console.log("Enabling block ruleset"); 14 await chrome.declarativeNetRequest.updateEnabledRulesets({ 15 enableRulesetIds: ["modifyResponseHeaders", "blockLoading"] 16 }); 17 } 18 }); 19 20 chrome.webRequest.onBeforeRequest.addListener( 21 async (details) => { 22 if (details.tabId === -1) return; 23 24 + const url = new URL(details.url); 25 + const hasUrl = scriptUrls.some((scriptUrl) => { 26 + return ( 27 + details.url.includes(scriptUrl) && 28 + !url.searchParams.has("inj") && 29 + (url.hostname.endsWith("discord.com") || url.hostname.endsWith("discordapp.com")) 30 + ); 31 + }); 32 + 33 + if (hasUrl) blockedScripts.add(details.url); 34 + 35 + if (blockedScripts.size === scriptUrls.length) { 36 + const blockedScriptsCopy = Array.from(blockedScripts); 37 + blockedScripts.clear(); 38 39 console.log("Running moonlight script"); 40 try { ··· 44 files: ["index.js"] 45 }); 46 } catch (e) { 47 + console.error(e); 48 } 49 50 console.log("Initializing moonlight"); ··· 56 try { 57 await window._moonlightBrowserInit(); 58 } catch (e) { 59 + console.error(e); 60 } 61 } 62 }); ··· 64 console.log(e); 65 } 66 67 + console.log("Disabling block ruleset"); 68 try { 69 await chrome.declarativeNetRequest.updateEnabledRulesets({ 70 disableRulesetIds: ["blockLoading"], 71 enableRulesetIds: ["modifyResponseHeaders"] 72 }); 73 } catch (e) { 74 + console.error(e); 75 } 76 77 console.log("Readding scripts"); ··· 79 await chrome.scripting.executeScript({ 80 target: { tabId: details.tabId }, 81 world: "MAIN", 82 + args: [blockedScriptsCopy], 83 + func: async (blockedScripts) => { 84 const scripts = [...document.querySelectorAll("script")].filter( 85 + (script) => script.src && blockedScripts.some((url) => url.includes(script.src)) 86 ); 87 88 + blockedScripts.reverse(); 89 + for (const url of blockedScripts) { 90 + if (url.includes("/sentry.")) continue; 91 92 + const script = scripts.find((script) => url.includes(script.src)); 93 const newScript = document.createElement("script"); 94 + for (const attr of script.attributes) { 95 + if (attr.name === "src") attr.value += "?inj"; 96 + newScript.setAttribute(attr.name, attr.value); 97 } 98 script.remove(); 99 document.documentElement.appendChild(newScript); 100 } 101 } 102 }); 103 } catch (e) { 104 + console.error(e); 105 } 106 } 107 }, 108 { 109 + urls: ["*://*.discord.com/assets/*.js", "*://*.discordapp.com/assets/*.js"] 110 } 111 );
+14 -12
packages/browser/src/index.ts
··· 6 import { MoonlightBranch, MoonlightNode } from "@moonlight-mod/types"; 7 import { getConfig, getConfigOption, getManifest, setConfigOption } from "@moonlight-mod/core/util/config"; 8 import { IndexedDB } from "@zenfs/dom"; 9 - import { configure } from "@zenfs/core"; 10 import * as fs from "@zenfs/core/promises"; 11 12 function getParts(path: string) { 13 if (path.startsWith("/")) path = path.substring(1); ··· 18 delete window._moonlightBrowserInit; 19 20 // Set up a virtual filesystem with IndexedDB 21 - await configure({ 22 - mounts: { 23 - "/": { 24 - backend: IndexedDB, 25 - // eslint-disable-next-line @typescript-eslint/ban-ts-comment 26 - // @ts-ignore tsc tweaking 27 - storeName: "moonlight-fs" 28 - } 29 - } 30 }); 31 32 window.moonlightNodeSandboxed = { ··· 94 dirname(path) { 95 const parts = getParts(path); 96 return "/" + parts.slice(0, parts.length - 1).join("/"); 97 } 98 }, 99 // TODO ··· 116 processedExtensions, 117 nativesCache: {}, 118 isBrowser: true, 119 120 version: MOONLIGHT_VERSION, 121 branch: MOONLIGHT_BRANCH as MoonlightBranch, ··· 127 const manifest = getManifest(extensions, ext); 128 return getConfigOption(ext, name, config, manifest?.settings); 129 }, 130 - setConfigOption(ext, name, value) { 131 setConfigOption(config, ext, name, value); 132 - this.writeConfig(config); 133 }, 134 135 getNatives: () => {}, ··· 147 async writeConfig(newConfig) { 148 await writeConfig(newConfig); 149 config = newConfig; 150 } 151 }; 152
··· 6 import { MoonlightBranch, MoonlightNode } from "@moonlight-mod/types"; 7 import { getConfig, getConfigOption, getManifest, setConfigOption } from "@moonlight-mod/core/util/config"; 8 import { IndexedDB } from "@zenfs/dom"; 9 + import { configureSingle } from "@zenfs/core"; 10 import * as fs from "@zenfs/core/promises"; 11 + import { NodeEventPayloads, NodeEventType } from "@moonlight-mod/types/core/event"; 12 + import { createEventEmitter } from "@moonlight-mod/core/util/event"; 13 14 function getParts(path: string) { 15 if (path.startsWith("/")) path = path.substring(1); ··· 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 = { ··· 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 ··· 116 processedExtensions, 117 nativesCache: {}, 118 isBrowser: true, 119 + events: createEventEmitter<NodeEventType, NodeEventPayloads>(), 120 121 version: MOONLIGHT_VERSION, 122 branch: MOONLIGHT_BRANCH as MoonlightBranch, ··· 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: () => {}, ··· 148 async writeConfig(newConfig) { 149 await writeConfig(newConfig); 150 config = newConfig; 151 + this.events.dispatchEvent(NodeEventType.ConfigSaved, newConfig); 152 } 153 }; 154
+1
packages/browser/tsconfig.json
··· 1 { 2 "extends": "../../tsconfig.json", 3 "compilerOptions": { 4 "module": "ES2022" 5 } 6 }
··· 1 { 2 "extends": "../../tsconfig.json", 3 "compilerOptions": { 4 + "lib": ["DOM", "ESNext", "ESNext.AsyncIterable"], 5 "module": "ES2022" 6 } 7 }
+7
packages/core/package.json
··· 4 "exports": { 5 "./*": "./src/*.ts" 6 }, 7 "dependencies": { 8 "@moonlight-mod/types": "workspace:*" 9 }
··· 4 "exports": { 5 "./*": "./src/*.ts" 6 }, 7 + "engineStrict": true, 8 + "engines": { 9 + "node": ">=22", 10 + "pnpm": ">=10", 11 + "npm": "pnpm", 12 + "yarn": "pnpm" 13 + }, 14 "dependencies": { 15 "@moonlight-mod/types": "workspace:*" 16 }
+5 -5
packages/core/src/extension/loader.ts
··· 13 import calculateDependencies from "../util/dependency"; 14 import { createEventEmitter } from "../util/event"; 15 import { registerStyles } from "../styles"; 16 - import { EventPayloads, EventType } from "@moonlight-mod/types/core/event"; 17 18 const logger = new Logger("core/extension/loader"); 19 ··· 202 } 203 204 export async function loadProcessedExtensions({ extensions, dependencyGraph }: ProcessedExtensions) { 205 - const eventEmitter = createEventEmitter<EventType, EventPayloads>(); 206 const finished: Set<string> = new Set(); 207 208 logger.trace( ··· 224 } 225 226 function done() { 227 - eventEmitter.removeEventListener(EventType.ExtensionLoad, cb); 228 r(); 229 } 230 231 - eventEmitter.addEventListener(EventType.ExtensionLoad, cb); 232 if (finished.has(dep)) done(); 233 }) 234 ); ··· 242 await loadExt(ext); 243 244 finished.add(ext.id); 245 - eventEmitter.dispatchEvent(EventType.ExtensionLoad, ext.id); 246 logger.debug(`Loaded "${ext.id}"`); 247 } 248
··· 13 import calculateDependencies from "../util/dependency"; 14 import { createEventEmitter } from "../util/event"; 15 import { registerStyles } from "../styles"; 16 + import { WebEventPayloads, WebEventType } from "@moonlight-mod/types/core/event"; 17 18 const logger = new Logger("core/extension/loader"); 19 ··· 202 } 203 204 export async function loadProcessedExtensions({ extensions, dependencyGraph }: ProcessedExtensions) { 205 + const eventEmitter = createEventEmitter<WebEventType, WebEventPayloads>(); 206 const finished: Set<string> = new Set(); 207 208 logger.trace( ··· 224 } 225 226 function done() { 227 + eventEmitter.removeEventListener(WebEventType.ExtensionLoad, cb); 228 r(); 229 } 230 231 + eventEmitter.addEventListener(WebEventType.ExtensionLoad, cb); 232 if (finished.has(dep)) done(); 233 }) 234 ); ··· 242 await loadExt(ext); 243 244 finished.add(ext.id); 245 + eventEmitter.dispatchEvent(WebEventType.ExtensionLoad, ext.id); 246 logger.debug(`Loaded "${ext.id}"`); 247 } 248
+1 -4
packages/core/src/extension.ts
··· 129 const ret: DetectedExtension[] = []; 130 const seen = new Set<string>(); 131 132 - const coreExtensionsFs: Record<string, string> = JSON.parse( 133 - // @ts-expect-error shut up 134 - _moonlight_coreExtensionsStr 135 - ); 136 const coreExtensions = Array.from(new Set(Object.keys(coreExtensionsFs).map((x) => x.split("/")[0]))); 137 138 for (const ext of coreExtensions) {
··· 129 const ret: DetectedExtension[] = []; 130 const seen = new Set<string>(); 131 132 + const coreExtensionsFs: Record<string, string> = JSON.parse(_moonlight_coreExtensionsStr); 133 const coreExtensions = Array.from(new Set(Object.keys(coreExtensionsFs).map((x) => x.split("/")[0]))); 134 135 for (const ext of coreExtensions) {
+3
packages/core/src/fs.ts
··· 48 }, 49 dirname(dir) { 50 return path.dirname(dir); 51 } 52 }; 53 }
··· 48 }, 49 dirname(dir) { 50 return path.dirname(dir); 51 + }, 52 + basename(dir) { 53 + return path.basename(dir); 54 } 55 }; 56 }
+57 -33
packages/core/src/patch.ts
··· 11 } from "@moonlight-mod/types"; 12 import Logger from "./util/logger"; 13 import calculateDependencies, { Dependency } from "./util/dependency"; 14 - import { EventType } from "@moonlight-mod/types/core/event"; 15 import { processFind, processReplace, testFind } from "./util/patch"; 16 17 const logger = new Logger("core/patch"); ··· 66 const moduleCache: Record<string, string> = {}; 67 const patched: Record<string, Array<string>> = {}; 68 69 - function patchModules(entry: WebpackJsonpEntry[1]) { 70 - function patchModule(id: string, patchId: string, replaced: string) { 71 - // Store what extensions patched what modules for easier debugging 72 - patched[id] = patched[id] || []; 73 - patched[id].push(patchId); 74 75 - // Webpack module arguments are minified, so we replace them with consistent names 76 - // We have to wrap it so things don't break, though 77 - const patchedStr = patched[id].sort().join(", "); 78 79 - const wrapped = 80 - `(${replaced}).apply(this, arguments)\n` + 81 - `// Patched by moonlight: ${patchedStr}\n` + 82 - `//# sourceURL=Webpack-Module-${id}`; 83 84 - try { 85 - const func = new Function("module", "exports", "require", wrapped) as WebpackModuleFunc; 86 - entry[id] = func; 87 - entry[id].__moonlight = true; 88 - return true; 89 - } catch (e) { 90 - logger.warn("Error constructing function for patch", patchId, e); 91 - patched[id].pop(); 92 - return false; 93 - } 94 } 95 96 // Populate the module cache 97 for (const [id, func] of Object.entries(entry)) { 98 if (!Object.hasOwn(moduleCache, id) && func.__moonlight !== true) { ··· 108 const origModuleString = moduleCache[id]; 109 let moduleString = origModuleString; 110 const patchedStr = []; 111 - const mappedName = moonlight.moonmap.modules[id]; 112 let modified = false; 113 114 const exts = new Set<string>(); 115 116 for (let i = 0; i < patches.length; i++) { 117 const patch = patches[i]; 118 if (patch.prerequisite != null && !patch.prerequisite()) { 119 continue; 120 } 121 ··· 135 // We ensured normal PatchReplace objects get turned into arrays on register 136 const replaces = patch.replace as PatchReplace[]; 137 138 for (let i = 0; i < replaces.length; i++) { 139 const replace = replaces[i]; 140 let patchId = `${patch.ext}#${patch.id}`; ··· 151 } 152 153 if (replaced === moduleString) { 154 - logger.warn("Patch replacement failed", id, patch); 155 if (patch.hardFail) { 156 hardFailed = true; 157 break; ··· 164 const newModule = replace.replacement(replaced); 165 entry[id] = newModule; 166 entry[id].__moonlight = true; 167 - replaced = replaced.toString().replace(/\n/g, "") + `//# sourceURL=Webpack-Module-${id}`; 168 } 169 } 170 ··· 174 exts.add(patch.ext); 175 } 176 177 - moonlight.unpatched.delete(patch); 178 if (shouldRemove) patches.splice(i--, 1); 179 } 180 } 181 182 if (modified) { 183 - patchModule(id, patchedStr.join(", "), moduleString); 184 - moduleCache[id] = moduleString; 185 moonlight.patched.set(id, exts); 186 } 187 ··· 189 const parsed = moonlight.lunast.parseScript(id, moduleString); 190 if (parsed != null) { 191 for (const [parsedId, parsedScript] of Object.entries(parsed)) { 192 - if (patchModule(parsedId, "lunast", parsedScript)) { 193 moduleCache[parsedId] = parsedScript; 194 } 195 } ··· 200 201 if (moonlightNode.config.patchAll === true) { 202 if ((typeof id !== "string" || !id.includes("_")) && !entry[id].__moonlight) { 203 - const wrapped = `(${moduleCache[id]}).apply(this, arguments)\n` + `//# sourceURL=Webpack-Module-${id}`; 204 entry[id] = new Function("module", "exports", "require", wrapped) as WebpackModuleFunc; 205 entry[id].__moonlight = true; 206 } ··· 308 if (wpModule.run) { 309 modules[id] = wpModule.run; 310 wpModule.run.__moonlight = true; 311 if (wpModule.entrypoint) entrypoints.push(id); 312 } 313 } ··· 315 } 316 317 for (const [name, func] of Object.entries(moonlight.moonmap.getWebpackModules("window.moonlight.moonmap"))) { 318 injectedWpModules.push({ id: name, run: func }); 319 modules[name] = func; 320 inject = true; ··· 392 const realPush = jsonp.push; 393 if (jsonp.push.__moonlight !== true) { 394 jsonp.push = (items) => { 395 - moonlight.events.dispatchEvent(EventType.ChunkLoad, { 396 chunkId: items[0], 397 modules: items[1], 398 require: items[2] ··· 440 set(modules: any) { 441 const { stack } = new Error(); 442 if (stack!.includes("/assets/") && !Array.isArray(modules)) { 443 - moonlight.events.dispatchEvent(EventType.ChunkLoad, { 444 modules: modules 445 }); 446 patchModules(modules);
··· 11 } from "@moonlight-mod/types"; 12 import Logger from "./util/logger"; 13 import calculateDependencies, { Dependency } from "./util/dependency"; 14 + import { WebEventType } from "@moonlight-mod/types/core/event"; 15 import { processFind, processReplace, testFind } from "./util/patch"; 16 17 const logger = new Logger("core/patch"); ··· 66 const moduleCache: Record<string, string> = {}; 67 const patched: Record<string, Array<string>> = {}; 68 69 + function createSourceURL(id: string) { 70 + const remapped = Object.entries(moonlight.moonmap.modules).find((m) => m[1] === id)?.[0]; 71 + 72 + if (remapped) { 73 + return `// Webpack Module: ${id}\n//# sourceURL=${remapped}`; 74 + } 75 76 + return `//# sourceURL=Webpack-Module/${id.slice(0, 3)}/${id}`; 77 + } 78 + 79 + function patchModule(id: string, patchId: string, replaced: string, entry: WebpackJsonpEntry[1]) { 80 + // Store what extensions patched what modules for easier debugging 81 + patched[id] = patched[id] ?? []; 82 + patched[id].push(patchId); 83 + 84 + // Webpack module arguments are minified, so we replace them with consistent names 85 + // We have to wrap it so things don't break, though 86 + const patchedStr = patched[id].sort().join(", "); 87 88 + const wrapped = 89 + `(${replaced}).apply(this, arguments)\n` + `// Patched by moonlight: ${patchedStr}\n` + createSourceURL(id); 90 91 + try { 92 + const func = new Function("module", "exports", "require", wrapped) as WebpackModuleFunc; 93 + entry[id] = func; 94 + entry[id].__moonlight = true; 95 + return true; 96 + } catch (e) { 97 + logger.warn("Error constructing function for patch", patchId, e); 98 + patched[id].pop(); 99 + return false; 100 } 101 + } 102 103 + function patchModules(entry: WebpackJsonpEntry[1]) { 104 // Populate the module cache 105 for (const [id, func] of Object.entries(entry)) { 106 if (!Object.hasOwn(moduleCache, id) && func.__moonlight !== true) { ··· 116 const origModuleString = moduleCache[id]; 117 let moduleString = origModuleString; 118 const patchedStr = []; 119 + const mappedName = Object.entries(moonlight.moonmap.modules).find((m) => m[1] === id)?.[0]; 120 let modified = false; 121 + let swappedModule = false; 122 123 const exts = new Set<string>(); 124 125 for (let i = 0; i < patches.length; i++) { 126 const patch = patches[i]; 127 if (patch.prerequisite != null && !patch.prerequisite()) { 128 + moonlight.unpatched.delete(patch); 129 continue; 130 } 131 ··· 145 // We ensured normal PatchReplace objects get turned into arrays on register 146 const replaces = patch.replace as PatchReplace[]; 147 148 + let isPatched = true; 149 for (let i = 0; i < replaces.length; i++) { 150 const replace = replaces[i]; 151 let patchId = `${patch.ext}#${patch.id}`; ··· 162 } 163 164 if (replaced === moduleString) { 165 + logger.warn("Patch replacement failed", id, patchId, patch); 166 + isPatched = false; 167 if (patch.hardFail) { 168 hardFailed = true; 169 break; ··· 176 const newModule = replace.replacement(replaced); 177 entry[id] = newModule; 178 entry[id].__moonlight = true; 179 + replaced = newModule.toString().replace(/\n/g, ""); 180 + swappedModule = true; 181 } 182 } 183 ··· 187 exts.add(patch.ext); 188 } 189 190 + if (isPatched) moonlight.unpatched.delete(patch); 191 if (shouldRemove) patches.splice(i--, 1); 192 } 193 } 194 195 if (modified) { 196 + let shouldCache = true; 197 + if (!swappedModule) shouldCache = patchModule(id, patchedStr.join(", "), moduleString, entry); 198 + if (shouldCache) moduleCache[id] = moduleString; 199 moonlight.patched.set(id, exts); 200 } 201 ··· 203 const parsed = moonlight.lunast.parseScript(id, moduleString); 204 if (parsed != null) { 205 for (const [parsedId, parsedScript] of Object.entries(parsed)) { 206 + if (patchModule(parsedId, "lunast", parsedScript, entry)) { 207 moduleCache[parsedId] = parsedScript; 208 } 209 } ··· 214 215 if (moonlightNode.config.patchAll === true) { 216 if ((typeof id !== "string" || !id.includes("_")) && !entry[id].__moonlight) { 217 + const wrapped = `(${moduleCache[id]}).apply(this, arguments)\n` + createSourceURL(id); 218 entry[id] = new Function("module", "exports", "require", wrapped) as WebpackModuleFunc; 219 entry[id].__moonlight = true; 220 } ··· 322 if (wpModule.run) { 323 modules[id] = wpModule.run; 324 wpModule.run.__moonlight = true; 325 + // @ts-expect-error hacks 326 + wpModule.run.call = function (self, module, exports, require) { 327 + try { 328 + wpModule.run!.apply(self, [module, exports, require]); 329 + } catch (err) { 330 + logger.error(`Failed to run module "${id}":`, err); 331 + } 332 + }; 333 if (wpModule.entrypoint) entrypoints.push(id); 334 } 335 } ··· 337 } 338 339 for (const [name, func] of Object.entries(moonlight.moonmap.getWebpackModules("window.moonlight.moonmap"))) { 340 + // @ts-expect-error probably should fix the type on this idk 341 + func.__moonlight = true; 342 injectedWpModules.push({ id: name, run: func }); 343 modules[name] = func; 344 inject = true; ··· 416 const realPush = jsonp.push; 417 if (jsonp.push.__moonlight !== true) { 418 jsonp.push = (items) => { 419 + moonlight.events.dispatchEvent(WebEventType.ChunkLoad, { 420 chunkId: items[0], 421 modules: items[1], 422 require: items[2] ··· 464 set(modules: any) { 465 const { stack } = new Error(); 466 if (stack!.includes("/assets/") && !Array.isArray(modules)) { 467 + moonlight.events.dispatchEvent(WebEventType.ChunkLoad, { 468 modules: modules 469 }); 470 patchModules(modules);
+4 -1
packages/core/tsconfig.json
··· 1 { 2 - "extends": "../../tsconfig.json" 3 }
··· 1 { 2 + "extends": "../../tsconfig.json", 3 + "compilerOptions": { 4 + "lib": ["ESNext", "DOM"] 5 + } 6 }
+9 -2
packages/core-extensions/package.json
··· 1 { 2 "name": "@moonlight-mod/core-extensions", 3 "private": true, 4 "dependencies": { 5 "@moonlight-mod/core": "workspace:*", 6 "@moonlight-mod/types": "workspace:*", 7 - "microdiff": "^1.5.0", 8 - "nanotar": "^0.1.1" 9 } 10 }
··· 1 { 2 "name": "@moonlight-mod/core-extensions", 3 "private": true, 4 + "engineStrict": true, 5 + "engines": { 6 + "node": ">=22", 7 + "pnpm": ">=10", 8 + "npm": "pnpm", 9 + "yarn": "pnpm" 10 + }, 11 "dependencies": { 12 "@moonlight-mod/core": "workspace:*", 13 "@moonlight-mod/types": "workspace:*", 14 + "microdiff": "catalog:prod", 15 + "nanotar": "catalog:prod" 16 } 17 }
+85
packages/core-extensions/src/commands/index.ts
···
··· 1 + import { Patch, ExtensionWebpackModule } from "@moonlight-mod/types"; 2 + import { APPLICATION_ID } from "@moonlight-mod/types/coreExtensions/commands"; 3 + 4 + export const patches: Patch[] = [ 5 + { 6 + find: ".fI5MTU)", // COMMAND_SECTION_BUILT_IN_NAME 7 + replace: [ 8 + // inject commands 9 + { 10 + match: /return (\i)\.filter/, 11 + replacement: (orig, commands) => 12 + `return [...${commands},...require("commands_commands").default._getCommands()].filter` 13 + }, 14 + 15 + // section 16 + { 17 + match: /(?<=\i={)(?=\[\i\.\i\.BUILT_IN]:{id:\i\.\i\.BUILT_IN,type:(\i.\i\.BUILT_IN))/, 18 + replacement: (_, type) => 19 + `"${APPLICATION_ID}":{id:"${APPLICATION_ID}",type:${type},get name(){return "moonlight"}},` 20 + } 21 + ] 22 + }, 23 + 24 + // index our section 25 + { 26 + find: '"ApplicationCommandIndexStore"', 27 + replace: { 28 + match: /(?<=let \i=(\i)\((\i\.\i)\[\i\.\i\.BUILT_IN\],(\i),!0,!0,(\i)\);)null!=(\i)&&(\i)\.push\(\i\)/, 29 + replacement: (_, createSection, sections, deny, props, section, commands) => 30 + `null!=${section}&&(${section}.data=${section}.data.filter(c=>c.applicationId=="-1")); 31 + null!=${section}&&${commands}.push(${section}); 32 + const moonlightCommands=${createSection}(${sections}["${APPLICATION_ID}"],${deny},!0,!0,${props}); 33 + null!=moonlightCommands&&(moonlightCommands.data=moonlightCommands.data.filter(c=>c.applicationId=="${APPLICATION_ID}")); 34 + null!=moonlightCommands&&${commands}.push(moonlightCommands)` 35 + } 36 + }, 37 + 38 + // grab legacy commands (needed for adding actions that act like sed/plus reacting) 39 + { 40 + find: "={tts:{action:", 41 + replace: { 42 + match: /Object\.setPrototypeOf\((\i),null\)/, 43 + replacement: (_, legacyCommands) => `require("commands_commands")._getLegacyCommands(${legacyCommands})` 44 + } 45 + }, 46 + 47 + // add icon 48 + { 49 + find: ",hasSpaceTerminator:", 50 + replace: { 51 + match: /(\i)\.type===/, 52 + replacement: (orig, section) => `${section}.id!=="${APPLICATION_ID}"&&${orig}` 53 + } 54 + }, 55 + { 56 + find: ".icon,bot:null==", 57 + replace: { 58 + match: /(\.useMemo\(\(\)=>{(var \i;)?)((return |if\()(\i)\.type)/, 59 + replacement: (_, before, beforeVar, after, afterIf, section) => `${before} 60 + if (${section}.id==="${APPLICATION_ID}") return "https://moonlight-mod.github.io/favicon.png"; 61 + ${after}` 62 + } 63 + }, 64 + // fix icon sizing because they expect built in to be 24 and others to be 32 65 + { 66 + find: ".builtInSeparator}):null]", 67 + replace: { 68 + match: /(\i)\.type===\i\.\i\.BUILT_IN/, 69 + replacement: (orig, section) => `${section}.id!=="${APPLICATION_ID}"&&${orig}` 70 + } 71 + }, 72 + 73 + // tell it this app id is authorized 74 + { 75 + find: /let{customInstallUrl:\i,installParams:\i,integrationTypesConfig:\i}/, 76 + replace: { 77 + match: /\|\|(\i)===\i\.\i\.BUILT_IN/, 78 + replacement: (orig, id) => `${orig}||${id}==="${APPLICATION_ID}"` 79 + } 80 + } 81 + ]; 82 + 83 + export const webpackModules: Record<string, ExtensionWebpackModule> = { 84 + commands: {} 85 + };
+11
packages/core-extensions/src/commands/manifest.json
···
··· 1 + { 2 + "$schema": "https://moonlight-mod.github.io/manifest.schema.json", 3 + "id": "commands", 4 + "apiLevel": 2, 5 + "meta": { 6 + "name": "Commands", 7 + "tagline": "A library to add commands", 8 + "authors": ["Cynosphere", "NotNite"], 9 + "tags": ["library"] 10 + } 11 + }
+71
packages/core-extensions/src/commands/webpackModules/commands.ts
···
··· 1 + import { 2 + APPLICATION_ID, 3 + Commands, 4 + LegacyCommand, 5 + RegisteredCommand 6 + } from "@moonlight-mod/types/coreExtensions/commands"; 7 + 8 + type LegacyCommands = Record<string, LegacyCommand>; 9 + let legacyCommands: LegacyCommands | undefined; 10 + let queuedLegacyCommands: Record<string, LegacyCommand> | null = {}; 11 + 12 + const registeredCommands: RegisteredCommand[] = []; 13 + 14 + export function _getLegacyCommands(commands: LegacyCommands) { 15 + legacyCommands = commands; 16 + if (queuedLegacyCommands != null) { 17 + for (const [key, value] of Object.entries(queuedLegacyCommands)) { 18 + legacyCommands[key] = value; 19 + } 20 + queuedLegacyCommands = null; 21 + } 22 + } 23 + 24 + export const commands: Commands = { 25 + registerCommand(command) { 26 + const registered: RegisteredCommand = { 27 + ...command, 28 + untranslatedName: command.id, 29 + displayName: command.id, 30 + applicationId: APPLICATION_ID, 31 + untranslatedDescription: command.description, 32 + displayDescription: command.description, 33 + options: command.options?.map((o) => ({ 34 + ...o, 35 + displayName: o.name, 36 + displayDescription: o.description 37 + })) 38 + }; 39 + registeredCommands.push(registered); 40 + }, 41 + 42 + registerLegacyCommand(id, command) { 43 + if (command.match) { 44 + if (command.match instanceof RegExp) { 45 + command.match = this.anyScopeRegex(command.match); 46 + } else if (command.match.regex && typeof command.match !== "function") { 47 + command.match = this.anyScopeRegex(command.match.regex); 48 + } 49 + } 50 + 51 + if (!legacyCommands) { 52 + queuedLegacyCommands![id] = command; 53 + } else { 54 + legacyCommands[id] = command; 55 + } 56 + }, 57 + 58 + anyScopeRegex(regex) { 59 + const out = function (str: string) { 60 + return regex.exec(str); 61 + }; 62 + out.regex = regex; 63 + return out; 64 + }, 65 + 66 + _getCommands() { 67 + return [...registeredCommands]; 68 + } 69 + }; 70 + 71 + export default commands;
+7 -5
packages/core-extensions/src/common/index.ts
··· 2 3 export const webpackModules: ExtensionWebExports["webpackModules"] = { 4 stores: { 5 - dependencies: [ 6 - { 7 - id: "discord/packages/flux" 8 - } 9 - ] 10 } 11 };
··· 2 3 export const webpackModules: ExtensionWebExports["webpackModules"] = { 4 stores: { 5 + dependencies: [{ id: "discord/packages/flux" }] 6 + }, 7 + ErrorBoundary: { 8 + dependencies: [{ id: "react" }] 9 + }, 10 + icons: { 11 + dependencies: [{ id: "react" }, { id: "discord/components/common/index" }] 12 } 13 };
+1 -1
packages/core-extensions/src/common/manifest.json
··· 4 "apiLevel": 2, 5 "meta": { 6 "name": "Common", 7 - "tagline": "A *lot* of common clientmodding utilities from the Discord client", 8 "authors": ["Cynosphere", "NotNite"], 9 "tags": ["library"] 10 },
··· 4 "apiLevel": 2, 5 "meta": { 6 "name": "Common", 7 + "tagline": "Common client modding utilities for the Discord client", 8 "authors": ["Cynosphere", "NotNite"], 9 "tags": ["library"] 10 },
+27
packages/core-extensions/src/common/style.css
···
··· 1 + .moonlight-error-boundary { 2 + margin: 0 0 15px; 3 + padding: 10px; 4 + border-radius: 5px; 5 + font-size: 1rem; 6 + font-weight: 300; 7 + line-height: 22px; 8 + color: var(--text-normal, white); 9 + background: hsl(var(--red-400-hsl) / 0.1); 10 + border: 2px solid hsl(var(--red-400-hsl) / 0.5); 11 + 12 + .theme-light & { 13 + color: var(--text-normal, black) !important; 14 + } 15 + 16 + & > h3 { 17 + margin-bottom: 0.25rem; 18 + } 19 + 20 + & > .hljs { 21 + background: var(--background-secondary); 22 + border: 1px solid var(--background-tertiary); 23 + white-space: pre-wrap; 24 + font-family: var(--font-code); 25 + user-select: text; 26 + } 27 + }
+47
packages/core-extensions/src/common/webpackModules/ErrorBoundary.tsx
···
··· 1 + import React from "@moonlight-mod/wp/react"; 2 + import { ErrorBoundaryProps, ErrorBoundaryState } from "@moonlight-mod/types/coreExtensions/common"; 3 + 4 + const logger = moonlight.getLogger("ErrorBoundary"); 5 + 6 + class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> { 7 + constructor(props: ErrorBoundaryProps) { 8 + super(props); 9 + this.state = { 10 + errored: false, 11 + error: undefined, 12 + componentStack: undefined 13 + }; 14 + } 15 + 16 + static getDerivedStateFromError(error: Error) { 17 + return { 18 + errored: true, 19 + error 20 + }; 21 + } 22 + 23 + componentDidCatch(error: Error, { componentStack }: { componentStack: string }) { 24 + logger.error(`${error}\n\nComponent stack:\n${componentStack}`); 25 + this.setState({ error, componentStack }); 26 + } 27 + 28 + render() { 29 + const { noop, fallback: FallbackComponent, children, message } = this.props; 30 + const { errored, error, componentStack } = this.state; 31 + 32 + if (FallbackComponent) return <FallbackComponent children={children} {...this.state} />; 33 + 34 + if (errored) { 35 + return noop ? null : ( 36 + <div className={`moonlight-error-boundary`}> 37 + <h3>{message ?? "An error occurred rendering this component:"}</h3> 38 + <code className="hljs">{`${error}\n\nComponent stack:\n${componentStack}`}</code> 39 + </div> 40 + ); 41 + } 42 + 43 + return children; 44 + } 45 + } 46 + 47 + export default ErrorBoundary;
+31
packages/core-extensions/src/common/webpackModules/icons.ts
···
··· 1 + import { Icons, IconSize } from "@moonlight-mod/types/coreExtensions/common"; 2 + import { tokens } from "@moonlight-mod/wp/discord/components/common/index"; 3 + 4 + // This is defined in a Webpack module but we copy it here to be less breakage-prone 5 + const sizes: Partial<Record<IconSize, number>> = { 6 + xxs: 12, 7 + xs: 16, 8 + sm: 18, 9 + md: 24, 10 + lg: 32, 11 + refresh_sm: 20 12 + }; 13 + 14 + export const icons: Icons = { 15 + parseProps(props) { 16 + // NOTE: var() fallback is non-standard behavior, just for safety reasons 17 + const color = props?.color ?? tokens?.colors?.["INTERACTIVE_NORMAL"] ?? "var(--interactive-normal)"; 18 + 19 + const size = sizes[props?.size ?? "md"]; 20 + 21 + return { 22 + // note: this default size is also non-standard behavior, just for safety 23 + width: size ?? props?.width ?? sizes.md!, 24 + height: size ?? props?.width ?? sizes.md!, 25 + 26 + fill: typeof color === "string" ? color : color.css, 27 + className: props?.colorClass ?? "" 28 + }; 29 + } 30 + }; 31 + export default icons;
+84
packages/core-extensions/src/componentEditor/index.ts
···
··· 1 + import { ExtensionWebpackModule, Patch } from "@moonlight-mod/types"; 2 + 3 + export const patches: Patch[] = [ 4 + // dm list 5 + { 6 + find: ".interactiveSystemDM]:", 7 + replace: [ 8 + { 9 + match: /decorators:(\i\.isSystemDM\(\)\?\(0,\i\.jsx\)\(.+?verified:!0}\):null)/, 10 + replacement: (_, decorators) => 11 + `decorators:require("componentEditor_dmList").default._patchDecorators([${decorators}],arguments[0])` 12 + }, 13 + { 14 + match: /(?<=selected:\i,)children:\[/, 15 + replacement: 'children:require("componentEditor_dmList").default._patchItems([' 16 + }, 17 + { 18 + match: /(?<=(onMouseDown|nameplate):\i}\))]/, 19 + replacement: "],arguments[0])" 20 + } 21 + ], 22 + hardFail: true 23 + }, 24 + 25 + // member list 26 + { 27 + find: ".lostPermission", 28 + replace: [ 29 + { 30 + match: 31 + /(?<=\(0,\i\.jsxs\)\(\i\.Fragment,{)children:(\[\(0,\i\.jsx\)\(\i,{user:\i}\),.+?onClickPremiumGuildIcon:\i}\)])/, 32 + replacement: (_, decorators) => 33 + `children:require("componentEditor_memberList").default._patchDecorators(${decorators},arguments[0])` 34 + }, 35 + { 36 + match: /name:null==\i\?\(0,\i\.jsx\)\("span"/, 37 + replacement: (orig: string) => 38 + `children:require("componentEditor_memberList").default._patchItems([],arguments[0]),${orig}` 39 + } 40 + ] 41 + }, 42 + 43 + // messages 44 + { 45 + find: '},"new-member")),', 46 + replace: [ 47 + { 48 + match: /(?<=\.BADGES](=|:))(\i)(;|})/, 49 + replacement: (_, leading, badges, trailing) => 50 + `require("componentEditor_messages").default._patchUsernameBadges(${badges},arguments[0])${trailing}` 51 + }, 52 + { 53 + match: /(?<=className:\i,)badges:(\i)/, 54 + replacement: (_, badges) => 55 + `badges:require("componentEditor_messages").default._patchBadges(${badges},arguments[0])` 56 + }, 57 + { 58 + match: /(?<=username:\(0,\i\.jsxs\)\(\i\.Fragment,{)children:(\[.+?])}\),usernameSpanId:/, 59 + replacement: (_, elements) => 60 + `children:require("componentEditor_messages").default._patchUsername(${elements},arguments[0])}),usernameSpanId:` 61 + } 62 + ] 63 + }, 64 + { 65 + find: '.provider&&"Discord"===', 66 + replace: { 67 + match: /(?<=\.container\),)children:(\[.+?this\.renderSuppressConfirmModal\(\),.+?\])}\)/, 68 + replacement: (_, elements) => 69 + `children:require("componentEditor_messages").default._patchAccessories(${elements},this.props)})` 70 + } 71 + } 72 + ]; 73 + 74 + export const webpackModules: Record<string, ExtensionWebpackModule> = { 75 + dmList: { 76 + dependencies: [{ id: "react" }] 77 + }, 78 + memberList: { 79 + dependencies: [{ id: "react" }] 80 + }, 81 + messages: { 82 + dependencies: [{ id: "react" }] 83 + } 84 + };
+11
packages/core-extensions/src/componentEditor/manifest.json
···
··· 1 + { 2 + "$schema": "https://moonlight-mod.github.io/manifest.schema.json", 3 + "id": "componentEditor", 4 + "apiLevel": 2, 5 + "meta": { 6 + "name": "Component Editor", 7 + "tagline": "A library to add to commonly patched components", 8 + "authors": ["Cynosphere"], 9 + "tags": ["library"] 10 + } 11 + }
+61
packages/core-extensions/src/componentEditor/webpackModules/dmList.tsx
···
··· 1 + import { 2 + DMList, 3 + DMListItem, 4 + DMListDecorator, 5 + DMListAnchorIndicies, 6 + DMListDecoratorAnchorIndicies 7 + } from "@moonlight-mod/types/coreExtensions/componentEditor"; 8 + import React from "@moonlight-mod/wp/react"; 9 + 10 + const items: Record<string, DMListItem> = {}; 11 + const decorators: Record<string, DMListDecorator> = {}; 12 + 13 + function addEntries( 14 + elements: React.ReactNode[], 15 + entries: Record<string, DMListItem | DMListDecorator>, 16 + indicies: Partial<Record<keyof typeof DMListAnchorIndicies | keyof typeof DMListDecoratorAnchorIndicies, number>>, 17 + props: any 18 + ) { 19 + const originalElements = [...elements]; 20 + for (const [id, entry] of Object.entries(entries)) { 21 + const component = <entry.component {...props} key={id} />; 22 + 23 + if (entry.anchor === undefined) { 24 + if (entry.before) { 25 + elements.splice(0, 0, component); 26 + } else { 27 + elements.push(component); 28 + } 29 + } else { 30 + const index = elements.indexOf(originalElements[indicies[entry.anchor]!]); 31 + elements.splice(index! + (entry.before ? 0 : 1), 0, component); 32 + } 33 + } 34 + } 35 + 36 + export const dmList: DMList = { 37 + addItem(id, component, anchor, before = false) { 38 + items[id] = { 39 + component, 40 + anchor, 41 + before 42 + }; 43 + }, 44 + addDecorator(id, component, anchor, before = false) { 45 + decorators[id] = { 46 + component, 47 + anchor, 48 + before 49 + }; 50 + }, 51 + _patchItems(elements, props) { 52 + addEntries(elements, items, DMListAnchorIndicies, props); 53 + return elements; 54 + }, 55 + _patchDecorators(elements, props) { 56 + addEntries(elements, decorators, DMListDecoratorAnchorIndicies, props); 57 + return elements; 58 + } 59 + }; 60 + 61 + export default dmList;
+50
packages/core-extensions/src/componentEditor/webpackModules/memberList.tsx
···
··· 1 + import { 2 + MemberList, 3 + MemberListDecorator, 4 + MemberListDecoratorAnchorIndicies 5 + } from "@moonlight-mod/types/coreExtensions/componentEditor"; 6 + import React from "@moonlight-mod/wp/react"; 7 + 8 + const items: Record<string, React.FC<any>> = {}; 9 + const decorators: Record<string, MemberListDecorator> = {}; 10 + 11 + export const memberList: MemberList = { 12 + addItem(id, component) { 13 + items[id] = component; 14 + }, 15 + addDecorator(id, component, anchor, before = false) { 16 + decorators[id] = { 17 + component, 18 + anchor, 19 + before 20 + }; 21 + }, 22 + _patchItems(elements, props) { 23 + for (const [id, Component] of Object.entries(items)) { 24 + elements.push(<Component {...props} key={id} />); 25 + } 26 + 27 + return elements; 28 + }, 29 + _patchDecorators(elements, props) { 30 + const originalElements = [...elements]; 31 + for (const [id, entry] of Object.entries(decorators)) { 32 + const component = <entry.component {...props} key={id} />; 33 + 34 + if (entry.anchor === undefined) { 35 + if (entry.before) { 36 + elements.splice(0, 0, component); 37 + } else { 38 + elements.push(component); 39 + } 40 + } else { 41 + const index = elements.indexOf(originalElements[MemberListDecoratorAnchorIndicies[entry.anchor]!]); 42 + elements.splice(index! + (entry.before ? 0 : 1), 0, component); 43 + } 44 + } 45 + 46 + return elements; 47 + } 48 + }; 49 + 50 + export default memberList;
+97
packages/core-extensions/src/componentEditor/webpackModules/messages.tsx
···
··· 1 + import { 2 + MessageBadge, 3 + MessageBadgeIndicies, 4 + Messages, 5 + MessageUsername, 6 + MessageUsernameBadge, 7 + MessageUsernameBadgeIndicies, 8 + MessageUsernameIndicies 9 + } from "@moonlight-mod/types/coreExtensions/componentEditor"; 10 + import React from "@moonlight-mod/wp/react"; 11 + 12 + const username: Record<string, MessageUsername> = {}; 13 + const usernameBadges: Record<string, MessageUsernameBadge> = {}; 14 + const badges: Record<string, MessageBadge> = {}; 15 + const accessories: Record<string, React.FC<any>> = {}; 16 + 17 + function addEntries( 18 + elements: React.ReactNode[], 19 + entries: Record<string, MessageUsername | MessageUsernameBadge | MessageBadge>, 20 + indicies: Partial< 21 + Record< 22 + | keyof typeof MessageUsernameIndicies 23 + | keyof typeof MessageUsernameBadgeIndicies 24 + | keyof typeof MessageBadgeIndicies, 25 + number 26 + > 27 + >, 28 + props: any 29 + ) { 30 + const originalElements = [...elements]; 31 + for (const [id, entry] of Object.entries(entries)) { 32 + const component = <entry.component {...props} key={id} />; 33 + 34 + if (entry.anchor === undefined) { 35 + if (entry.before) { 36 + elements.splice(0, 0, component); 37 + } else { 38 + elements.push(component); 39 + } 40 + } else { 41 + const index = elements.indexOf(originalElements[indicies[entry.anchor]!]); 42 + elements.splice(index! + (entry.before ? 0 : 1), 0, component); 43 + } 44 + } 45 + } 46 + 47 + function addComponents(elements: React.ReactNode[], components: Record<string, React.FC<any>>, props: any) { 48 + for (const [id, Component] of Object.entries(components)) { 49 + const component = <Component {...props} key={id} />; 50 + elements.push(component); 51 + } 52 + } 53 + 54 + export const messages: Messages = { 55 + addToUsername(id, component, anchor, before = false) { 56 + username[id] = { 57 + component, 58 + anchor, 59 + before 60 + }; 61 + }, 62 + addUsernameBadge(id, component, anchor, before = false) { 63 + usernameBadges[id] = { 64 + component, 65 + anchor, 66 + before 67 + }; 68 + }, 69 + addBadge(id, component, anchor, before = false) { 70 + badges[id] = { 71 + component, 72 + anchor, 73 + before 74 + }; 75 + }, 76 + addAccessory(id, component) { 77 + accessories[id] = component; 78 + }, 79 + _patchUsername(elements, props) { 80 + addEntries(elements, username, MessageUsernameIndicies, props); 81 + return elements; 82 + }, 83 + _patchUsernameBadges(elements, props) { 84 + addEntries(elements, usernameBadges, MessageUsernameBadgeIndicies, props); 85 + return elements; 86 + }, 87 + _patchBadges(elements, props) { 88 + addEntries(elements, badges, MessageBadgeIndicies, props); 89 + return elements; 90 + }, 91 + _patchAccessories(elements, props) { 92 + addComponents(elements, accessories, props); 93 + return elements; 94 + } 95 + }; 96 + 97 + export default messages;
+1
packages/core-extensions/src/contextMenu/webpackModules/contextMenu.ts
··· 58 }; 59 60 // Unmangle Menu elements 61 const code = 62 spacepack.require.m[ 63 spacepack.findByCode("Menu API only allows Items and groups of Items as children.")[0].id
··· 58 }; 59 60 // Unmangle Menu elements 61 + // spacepack.require.m[moonlight.moonmap.modules["discord/modules/menus/web/Menu"]].toString(); 62 const code = 63 spacepack.require.m[ 64 spacepack.findByCode("Menu API only allows Items and groups of Items as children.")[0].id
+2 -1
packages/core-extensions/src/contextMenu/webpackModules/evilMenu.ts
··· 1 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 2 3 let code = 4 spacepack.require.m[ 5 spacepack.findByCode("Menu API only allows Items and groups of Items as children.")[0].id ··· 7 8 const parserSym = code.match(/(?<=_patchMenu\(.,).+?(?=\()/)![0]; 9 10 - code = code.replace(/(?<=function\(\){return ).(?=})/, parserSym); 11 const mod = new Function("module", "exports", "require", `(${code}).apply(this, arguments)`); 12 13 const exp: any = {};
··· 1 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 2 3 + // spacepack.require.m[moonlight.moonmap.modules["discord/modules/menus/web/Menu"]].toString(); 4 let code = 5 spacepack.require.m[ 6 spacepack.findByCode("Menu API only allows Items and groups of Items as children.")[0].id ··· 8 9 const parserSym = code.match(/(?<=_patchMenu\(.,).+?(?=\()/)![0]; 10 11 + code = code.replace(/{(.):\(\)=>./, (orig, e) => `{${e}:()=>${parserSym}`); 12 const mod = new Function("module", "exports", "require", `(${code}).apply(this, arguments)`); 13 14 const exp: any = {};
+2 -2
packages/core-extensions/src/disableSentry/index.ts
··· 6 find: "profiledRootComponent:", 7 replace: { 8 type: PatchReplaceType.Normal, 9 - match: /(?<=\.Z=){.+?}}/, 10 - replacement: 'require("disableSentry_stub").proxy()' 11 } 12 }, 13 {
··· 6 find: "profiledRootComponent:", 7 replace: { 8 type: PatchReplaceType.Normal, 9 + match: /Z:\(\)=>\i/, 10 + replacement: 'Z:()=>require("disableSentry_stub").proxy()' 11 } 12 }, 13 {
+4 -1
packages/core-extensions/src/disableSentry/manifest.json
··· 12 "https://*.sentry.io/*", 13 "https://*.discord.com/error-reporting-proxy/*", 14 "https://discord.com/assets/sentry.*.js", 15 - "https://*.discord.com/assets/sentry.*.js" 16 ] 17 }
··· 12 "https://*.sentry.io/*", 13 "https://*.discord.com/error-reporting-proxy/*", 14 "https://discord.com/assets/sentry.*.js", 15 + "https://*.discord.com/assets/sentry.*.js", 16 + "https://*.discordapp.com/error-reporting-proxy/*", 17 + "https://discordapp.com/assets/sentry.*.js", 18 + "https://*.discordapp.com/assets/sentry.*.js" 19 ] 20 }
+23 -6
packages/core-extensions/src/experiments/index.ts
··· 11 { 12 find: '"scientist:triggered"', // Scientist? Triggered. 13 replace: { 14 - match: /(?<=personal_connection_id\|\|)!1/, 15 - replacement: "!0" 16 } 17 }, 18 ··· 20 { 21 find: ".HEADER_BAR)", 22 replace: { 23 - match: /&&\((.)\?\(0,/, 24 replacement: (_, isStaff) => 25 `&&(((moonlight.getConfigOption("experiments","devtools")??false)?true:${isStaff})?(0,` 26 } 27 }, 28 29 // Enable further staff-locked options 30 { 31 find: "shouldShowLurkerModeUpsellPopout:", 32 replace: { 33 - match: /\.useReducedMotion,isStaff:(.),/, 34 - replacement: (_, isStaff) => 35 - `.useReducedMotion,isStaff:(moonlight.getConfigOption("experiments","staffSettings")??false)?true:${isStaff},` 36 } 37 } 38 ];
··· 11 { 12 find: '"scientist:triggered"', // Scientist? Triggered. 13 replace: { 14 + match: ".personal_connection_id", 15 + replacement: ".personal_connection_id || true" 16 } 17 }, 18 ··· 20 { 21 find: ".HEADER_BAR)", 22 replace: { 23 + match: /&&\((\i)\?\(0,/, 24 replacement: (_, isStaff) => 25 `&&(((moonlight.getConfigOption("experiments","devtools")??false)?true:${isStaff})?(0,` 26 } 27 }, 28 + // staff help menu - visual refresh 29 + { 30 + find: '("AppTitleBar")', 31 + replace: { 32 + match: /{hasBugReporterAccess:(\i)}=\i\.\i\.useExperiment\({location:"HeaderBar"},{autoTrackExposure:!1}\);/, 33 + replacement: (orig, isStaff) => 34 + `${orig}if(moonlight.getConfigOption("experiments","devtools")??false)${isStaff}=true;` 35 + } 36 + }, 37 + { 38 + find: 'navId:"staff-help-popout",', 39 + replace: { 40 + match: /isDiscordDeveloper:(\i)}\),/, 41 + replacement: (_, isStaff) => 42 + `isDiscordDeveloper:(moonlight.getConfigOption("experiments","devtools")??false)||${isStaff}}),` 43 + } 44 + }, 45 46 // Enable further staff-locked options 47 { 48 find: "shouldShowLurkerModeUpsellPopout:", 49 replace: { 50 + match: /\.useReducedMotion,isStaff:(\i)(,|})/, 51 + replacement: (_, isStaff, trail) => 52 + `.useReducedMotion,isStaff:(moonlight.getConfigOption("experiments","staffSettings")??false)?true:${isStaff}${trail}` 53 } 54 } 55 ];
+38 -7
packages/core-extensions/src/moonbase/host.ts
··· 2 import * as fs from "node:fs/promises"; 3 import * as path from "node:path"; 4 import getNatives from "./native"; 5 6 const natives = getNatives(); 7 ··· 50 electron.app.exit(0); 51 } 52 53 function showAbout() { 54 electron.dialog.showMessageBox({ 55 title: "About moonlight", ··· 63 const i = entries.findIndex((e) => e.label === "Check for Updates..."); 64 if (i === -1) return original.call(this, entries); 65 66 - entries.splice(i + 1, 0, { 67 - label: "moonlight", 68 - submenu: [ 69 { label: "Update and restart", click: updateAndRestart }, 70 - { label: "Reset config", click: resetConfig }, 71 - { label: "About", click: showAbout } 72 - ] 73 - }); 74 75 return original.call(this, entries); 76 };
··· 2 import * as fs from "node:fs/promises"; 3 import * as path from "node:path"; 4 import getNatives from "./native"; 5 + import { MoonlightBranch } from "@moonlight-mod/types"; 6 7 const natives = getNatives(); 8 ··· 51 electron.app.exit(0); 52 } 53 54 + async function changeBranch(branch: MoonlightBranch) { 55 + if (moonlightHost.branch === branch) return; 56 + if (!(await confirm("switch branches"))) return; 57 + try { 58 + await natives.updateMoonlight(branch); 59 + await electron.dialog.showMessageBox({ message: "Branch switch successful, restarting Discord." }); 60 + electron.app.relaunch(); 61 + electron.app.exit(0); 62 + } catch (e) { 63 + await electron.dialog.showMessageBox({ message: "Failed to switch branches:\n" + e, type: "error" }); 64 + } 65 + } 66 + 67 function showAbout() { 68 electron.dialog.showMessageBox({ 69 title: "About moonlight", ··· 77 const i = entries.findIndex((e) => e.label === "Check for Updates..."); 78 if (i === -1) return original.call(this, entries); 79 80 + if (!entries.find((e) => e.label === "moonlight")) { 81 + const options: Electron.MenuItemConstructorOptions[] = [ 82 { label: "Update and restart", click: updateAndRestart }, 83 + { label: "Reset config", click: resetConfig } 84 + ]; 85 + 86 + if (moonlightHost.branch !== MoonlightBranch.DEV) { 87 + options.push({ 88 + label: "Switch branch", 89 + submenu: [MoonlightBranch.STABLE, MoonlightBranch.NIGHTLY].map((branch) => ({ 90 + label: branch, 91 + type: "radio", 92 + checked: moonlightHost.branch === branch, 93 + click: () => changeBranch(branch) 94 + })) 95 + }); 96 + } 97 + 98 + options.push({ label: "About", click: showAbout }); 99 + 100 + entries.splice(i + 1, 0, { 101 + label: "moonlight", 102 + submenu: options 103 + }); 104 + } 105 106 return original.call(this, entries); 107 };
+13 -4
packages/core-extensions/src/moonbase/index.tsx
··· 8 { 9 // CvQlAA mapped to ERRORS_ACTION_TO_TAKE 10 // FIXME: Better patch find? 11 - match: /,(\(0,(.)\.jsx\))\("p",{children:.\.intl\.string\(.\..\.CvQlAA\)}\)/, 12 replacement: (_, createElement, ReactJSX) => 13 `,${createElement}(require("moonbase_crashScreen")?.UpdateText??${ReactJSX}.Fragment,{state:this.state,setState:this.setState.bind(this)})` 14 }, 15 16 // wrap actions field to display error details 17 { 18 - match: /(?<=return(\(0,(.)\.jsx\))\(.+?,)action:(.),className:/, 19 replacement: (_, createElement, ReactJSX, action) => 20 `action:require("moonbase_crashScreen")?.wrapAction?${createElement}(require("moonbase_crashScreen").wrapAction,{action:${action},state:this.state}):${action},className:` 21 }, ··· 23 // add update button 24 // +hivLS -> ERRORS_RELOAD 25 { 26 - match: /(?<=\["\+hivLS"\]\)}\),(\(0,(.)\.jsx\))\(.,{}\))/, 27 replacement: (_, createElement, ReactJSX) => 28 `,${createElement}(require("moonbase_crashScreen")?.UpdateButton??${ReactJSX}.Fragment,{state:this.state,setState:this.setState.bind(this)})` 29 } ··· 42 { id: "react" }, 43 { id: "discord/components/common/index" }, 44 { ext: "moonbase", id: "stores" }, 45 - { id: "discord/modules/guild_settings/IntegrationCard.css" }, 46 "Masks.PANEL_BUTTON", 47 '"Missing channel in Channel.openChannelContextMenu"', 48 ".forumOrHome]:" 49 ] 50 }, 51 52 settings: { 53 dependencies: [ 54 { ext: "spacepack", id: "spacepack" }, 55 { ext: "settings", id: "settings" }, 56 { id: "react" }, 57 { ext: "moonbase", id: "ui" }, 58 ':"USER_SETTINGS_MODAL_SET_SECTION"' 59 ], 60 entrypoint: true ··· 64 dependencies: [ 65 { id: "react" }, 66 { ext: "moonbase", id: "stores" }, 67 { ext: "notices", id: "notices" }, 68 { 69 ext: "spacepack",
··· 8 { 9 // CvQlAA mapped to ERRORS_ACTION_TO_TAKE 10 // FIXME: Better patch find? 11 + match: /,(\(0,(\i)\.jsx\))\("p",{children:\i\.\i\.string\(\i\.\i\.CvQlAA\)}\)/, 12 replacement: (_, createElement, ReactJSX) => 13 `,${createElement}(require("moonbase_crashScreen")?.UpdateText??${ReactJSX}.Fragment,{state:this.state,setState:this.setState.bind(this)})` 14 }, 15 16 // wrap actions field to display error details 17 { 18 + match: /(?<=return(\(0,(\i)\.jsx\))\(.+?,)action:(\i),className:/, 19 replacement: (_, createElement, ReactJSX, action) => 20 `action:require("moonbase_crashScreen")?.wrapAction?${createElement}(require("moonbase_crashScreen").wrapAction,{action:${action},state:this.state}):${action},className:` 21 }, ··· 23 // add update button 24 // +hivLS -> ERRORS_RELOAD 25 { 26 + match: /(?<=\["\+hivLS"\]\)}\),(\(0,(\i)\.jsx\))\(\i,{}\))/, 27 replacement: (_, createElement, ReactJSX) => 28 `,${createElement}(require("moonbase_crashScreen")?.UpdateButton??${ReactJSX}.Fragment,{state:this.state,setState:this.setState.bind(this)})` 29 } ··· 42 { id: "react" }, 43 { id: "discord/components/common/index" }, 44 { ext: "moonbase", id: "stores" }, 45 + { ext: "moonbase", id: "ThemeDarkIcon" }, 46 + { id: "discord/modules/guild_settings/web/AppCard.css" }, 47 + { ext: "contextMenu", id: "contextMenu" }, 48 + { id: "discord/modules/modals/Modals" }, 49 "Masks.PANEL_BUTTON", 50 '"Missing channel in Channel.openChannelContextMenu"', 51 ".forumOrHome]:" 52 ] 53 }, 54 55 + ThemeDarkIcon: { 56 + dependencies: [{ ext: "common", id: "icons" }, { id: "react" }] 57 + }, 58 + 59 settings: { 60 dependencies: [ 61 { ext: "spacepack", id: "spacepack" }, 62 { ext: "settings", id: "settings" }, 63 { id: "react" }, 64 { ext: "moonbase", id: "ui" }, 65 + { ext: "contextMenu", id: "contextMenu" }, 66 ':"USER_SETTINGS_MODAL_SET_SECTION"' 67 ], 68 entrypoint: true ··· 72 dependencies: [ 73 { id: "react" }, 74 { ext: "moonbase", id: "stores" }, 75 + { ext: "moonbase", id: "ThemeDarkIcon" }, 76 { ext: "notices", id: "notices" }, 77 { 78 ext: "spacepack",
+11 -3
packages/core-extensions/src/moonbase/manifest.json
··· 7 "tagline": "The official settings UI for moonlight", 8 "authors": ["Cynosphere", "NotNite", "redstonekasi"] 9 }, 10 - "dependencies": ["spacepack", "settings", "common", "notices"], 11 "settings": { 12 "sections": { 13 "advice": "reload", 14 "displayName": "Split into sections", 15 "description": "Show the Moonbase tabs as separate sections", 16 - "type": "boolean" 17 }, 18 "saveFilter": { 19 "advice": "none", 20 "displayName": "Persist filter", 21 "description": "Save extension filter in config", 22 - "type": "boolean" 23 }, 24 "updateChecking": { 25 "advice": "none",
··· 7 "tagline": "The official settings UI for moonlight", 8 "authors": ["Cynosphere", "NotNite", "redstonekasi"] 9 }, 10 + "dependencies": ["spacepack", "settings", "common", "notices", "contextMenu"], 11 "settings": { 12 "sections": { 13 "advice": "reload", 14 "displayName": "Split into sections", 15 "description": "Show the Moonbase tabs as separate sections", 16 + "type": "boolean", 17 + "default": false 18 + }, 19 + "oldLocation": { 20 + "advice": "reload", 21 + "displayName": "Put Moonbase back at the bottom", 22 + "type": "boolean", 23 + "default": false 24 }, 25 "saveFilter": { 26 "advice": "none", 27 "displayName": "Persist filter", 28 "description": "Save extension filter in config", 29 + "type": "boolean", 30 + "default": false 31 }, 32 "updateChecking": { 33 "advice": "none",
+17 -24
packages/core-extensions/src/moonbase/native.ts
··· 15 16 export const userAgent = `moonlight/${moonlightGlobal.version} (https://github.com/moonlight-mod/moonlight)`; 17 18 async function getStableRelease(): Promise<{ 19 name: string; 20 assets: { ··· 24 }> { 25 const req = await fetch(githubApiUrl, { 26 cache: "no-store", 27 - headers: { 28 - "User-Agent": userAgent 29 - } 30 }); 31 return await req.json(); 32 } ··· 43 } else if (moonlightGlobal.branch === MoonlightBranch.NIGHTLY) { 44 const req = await fetch(nightlyRefUrl, { 45 cache: "no-store", 46 - headers: { 47 - "User-Agent": userAgent 48 - } 49 }); 50 const ref = (await req.text()).split("\n")[0]; 51 return ref !== moonlightGlobal.version ? ref : null; ··· 58 } 59 }, 60 61 - async updateMoonlight() { 62 // Note: this won't do anything on browser, we should probably disable it 63 // entirely when running in browser. 64 async function downloadStable(): Promise<[ArrayBuffer, string]> { ··· 69 logger.debug(`Downloading ${asset.browser_download_url}`); 70 const req = await fetch(asset.browser_download_url, { 71 cache: "no-store", 72 - headers: { 73 - "User-Agent": userAgent 74 - } 75 }); 76 77 return [await req.arrayBuffer(), json.name]; ··· 81 logger.debug(`Downloading ${nightlyZipUrl}`); 82 const zipReq = await fetch(nightlyZipUrl, { 83 cache: "no-store", 84 - headers: { 85 - "User-Agent": userAgent 86 - } 87 }); 88 89 const refReq = await fetch(nightlyRefUrl, { 90 cache: "no-store", 91 - headers: { 92 - "User-Agent": userAgent 93 - } 94 }); 95 const ref = (await refReq.text()).split("\n")[0]; 96 ··· 98 } 99 100 const [tar, ref] = 101 - moonlightGlobal.branch === MoonlightBranch.STABLE 102 ? await downloadStable() 103 - : moonlightGlobal.branch === MoonlightBranch.NIGHTLY 104 ? await downloadNightly() 105 : [null, null]; 106 ··· 137 try { 138 const req = await fetch(repo, { 139 cache: "no-store", 140 - headers: { 141 - "User-Agent": userAgent 142 - } 143 }); 144 const json = await req.json(); 145 ret[repo] = json; ··· 154 async installExtension(manifest, url, repo) { 155 const req = await fetch(url, { 156 cache: "no-store", 157 - headers: { 158 - "User-Agent": userAgent 159 - } 160 }); 161 162 const dir = moonlightGlobal.getExtensionDir(manifest.id);
··· 15 16 export const userAgent = `moonlight/${moonlightGlobal.version} (https://github.com/moonlight-mod/moonlight)`; 17 18 + // User-Agent header causes trouble on Firefox 19 + const isBrowser = globalThis.moonlightNode != null && globalThis.moonlightNode.isBrowser; 20 + const sharedHeaders: Record<string, string> = {}; 21 + if (!isBrowser) sharedHeaders["User-Agent"] = userAgent; 22 + 23 async function getStableRelease(): Promise<{ 24 name: string; 25 assets: { ··· 29 }> { 30 const req = await fetch(githubApiUrl, { 31 cache: "no-store", 32 + headers: sharedHeaders 33 }); 34 return await req.json(); 35 } ··· 46 } else if (moonlightGlobal.branch === MoonlightBranch.NIGHTLY) { 47 const req = await fetch(nightlyRefUrl, { 48 cache: "no-store", 49 + headers: sharedHeaders 50 }); 51 const ref = (await req.text()).split("\n")[0]; 52 return ref !== moonlightGlobal.version ? ref : null; ··· 59 } 60 }, 61 62 + async updateMoonlight(overrideBranch?: MoonlightBranch) { 63 + const branch = overrideBranch ?? moonlightGlobal.branch; 64 + 65 // Note: this won't do anything on browser, we should probably disable it 66 // entirely when running in browser. 67 async function downloadStable(): Promise<[ArrayBuffer, string]> { ··· 72 logger.debug(`Downloading ${asset.browser_download_url}`); 73 const req = await fetch(asset.browser_download_url, { 74 cache: "no-store", 75 + headers: sharedHeaders 76 }); 77 78 return [await req.arrayBuffer(), json.name]; ··· 82 logger.debug(`Downloading ${nightlyZipUrl}`); 83 const zipReq = await fetch(nightlyZipUrl, { 84 cache: "no-store", 85 + headers: sharedHeaders 86 }); 87 88 const refReq = await fetch(nightlyRefUrl, { 89 cache: "no-store", 90 + headers: sharedHeaders 91 }); 92 const ref = (await refReq.text()).split("\n")[0]; 93 ··· 95 } 96 97 const [tar, ref] = 98 + branch === MoonlightBranch.STABLE 99 ? await downloadStable() 100 + : branch === MoonlightBranch.NIGHTLY 101 ? await downloadNightly() 102 : [null, null]; 103 ··· 134 try { 135 const req = await fetch(repo, { 136 cache: "no-store", 137 + headers: sharedHeaders 138 }); 139 const json = await req.json(); 140 ret[repo] = json; ··· 149 async installExtension(manifest, url, repo) { 150 const req = await fetch(url, { 151 cache: "no-store", 152 + headers: sharedHeaders 153 }); 154 155 const dir = moonlightGlobal.getExtensionDir(manifest.id);
+63
packages/core-extensions/src/moonbase/style.css
··· 16 resize: vertical; 17 } 18 19 /* Update notice at the top of the client */ 20 .moonbase-updates-notice { 21 background-color: var(--moonbase-bg); ··· 73 display: flex; 74 flex-direction: row; 75 gap: 8px; 76 } 77 78 .moonbase-update-divider { 79 margin: 32px 0; 80 } 81 82 /* Crash screen */ ··· 204 line-height: 1.286; 205 font-weight: 400; 206 }
··· 16 resize: vertical; 17 } 18 19 + .moonbase-link-buttons { 20 + border-bottom: 2px solid var(--background-modifier-accent); 21 + margin-bottom: -2px; 22 + margin-left: 0 !important; 23 + padding-right: 20px; 24 + gap: 1rem; 25 + } 26 + 27 + .moonbase-speen { 28 + animation: moonbase-speen-animation 0.25s linear infinite; 29 + } 30 + 31 + @keyframes moonbase-speen-animation { 32 + from { 33 + transform: rotate(0deg); 34 + } 35 + to { 36 + transform: rotate(360deg); 37 + } 38 + } 39 + 40 /* Update notice at the top of the client */ 41 .moonbase-updates-notice { 42 background-color: var(--moonbase-bg); ··· 94 display: flex; 95 flex-direction: row; 96 gap: 8px; 97 + align-items: center; 98 } 99 100 .moonbase-update-divider { 101 margin: 32px 0; 102 + } 103 + 104 + .moonlight-card-info-header { 105 + margin-bottom: 0.25rem; 106 + } 107 + 108 + .moonlight-card-badge { 109 + border-radius: 0.1875rem; 110 + padding: 0 0.275rem; 111 + margin-right: 0.4em; 112 + background-color: var(--badge-color, var(--bg-mod-strong)); 113 } 114 115 /* Crash screen */ ··· 237 line-height: 1.286; 238 font-weight: 400; 239 } 240 + 241 + /* About page */ 242 + .moonbase-wordmark { 243 + width: 100%; 244 + } 245 + 246 + .moonbase-devs { 247 + width: 100%; 248 + display: flex; 249 + justify-content: center; 250 + gap: 0rem 0.5rem; 251 + padding-top: 0.5rem; 252 + } 253 + 254 + .moonbase-dev { 255 + height: 4rem; 256 + } 257 + 258 + .moonbase-dev-avatar { 259 + width: 2rem; 260 + border-radius: 50%; 261 + } 262 + 263 + .moonbase-gap { 264 + gap: 0.5rem; 265 + } 266 + 267 + .moonbase-about-page { 268 + gap: 1rem; 269 + }
+2 -2
packages/core-extensions/src/moonbase/types.ts
··· 1 import { ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 2 - import { DetectedExtension, ExtensionManifest } from "@moonlight-mod/types"; 3 4 export type MoonbaseNatives = { 5 checkForMoonlightUpdate(): Promise<string | null>; 6 - updateMoonlight(): Promise<void>; 7 8 fetchRepositories(repos: string[]): Promise<Record<string, RepositoryManifest[]>>; 9 installExtension(manifest: RepositoryManifest, url: string, repo: string): Promise<void>;
··· 1 import { ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 2 + import { DetectedExtension, ExtensionManifest, MoonlightBranch } from "@moonlight-mod/types"; 3 4 export type MoonbaseNatives = { 5 checkForMoonlightUpdate(): Promise<string | null>; 6 + updateMoonlight(overrideBranch?: MoonlightBranch): Promise<void>; 7 8 fetchRepositories(repos: string[]): Promise<Record<string, RepositoryManifest[]>>; 9 installExtension(manifest: RepositoryManifest, url: string, repo: string): Promise<void>;
+36
packages/core-extensions/src/moonbase/webpackModules/ThemeDarkIcon.tsx
···
··· 1 + // RIP to ThemeDarkIcon ????-2025 2 + // <Cynthia> Failed to remap "ThemeDarkIcon" in "discord/components/common/index" 3 + // <NotNite> bro are you fucking kidding me 4 + // <NotNite> that's literally the icon we use for the update banner 5 + 6 + import React from "@moonlight-mod/wp/react"; 7 + import icons from "@moonlight-mod/wp/common_icons"; 8 + import type { IconProps } from "@moonlight-mod/types/coreExtensions/common"; 9 + 10 + export default function ThemeDarkIcon(props?: IconProps) { 11 + const parsed = icons.parseProps(props); 12 + 13 + return ( 14 + <svg 15 + aria-hidden="true" 16 + role="img" 17 + xmlns="http://www.w3.org/2000/svg" 18 + width={parsed.width} 19 + height={parsed.height} 20 + fill="none" 21 + viewBox="0 0 24 24" 22 + > 23 + <path 24 + fill={parsed.fill} 25 + className={parsed.className} 26 + d="M20.52 18.96c.32-.4-.01-.96-.52-.96A11 11 0 0 1 9.77 2.94c.31-.78-.3-1.68-1.1-1.43a11 11 0 1 0 11.85 17.45Z" 27 + /> 28 + 29 + <path 30 + fill={parsed.fill} 31 + className={parsed.className} 32 + d="m17.73 9.27-.76-2.02a.5.5 0 0 0-.94 0l-.76 2.02-2.02.76a.5.5 0 0 0 0 .94l2.02.76.76 2.02a.5.5 0 0 0 .94 0l.76-2.02 2.02-.76a.5.5 0 0 0 0-.94l-2.02-.76ZM19.73 2.62l.45 1.2 1.2.45c.21.08.21.38 0 .46l-1.2.45-.45 1.2a.25.25 0 0 1-.46 0l-.45-1.2-1.2-.45a.25.25 0 0 1 0-.46l1.2-.45.45-1.2a.25.25 0 0 1 .46 0Z" 33 + /> 34 + </svg> 35 + ); 36 + }
+27 -14
packages/core-extensions/src/moonbase/webpackModules/crashScreen.tsx
··· 1 import React from "@moonlight-mod/wp/react"; 2 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 3 import { useStateFromStores, useStateFromStoresObject } from "@moonlight-mod/wp/discord/packages/flux"; 4 - import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 5 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 6 import { RepositoryManifest, UpdateState } from "../types"; 7 import { ConfigExtension, DetectedExtension } from "@moonlight-mod/types"; 8 9 - const { Button, TabBar } = Components; 10 - const TabBarClasses = spacepack.findByCode(/tabBar:"tabBar_[a-z0-9]+",tabBarItem:"tabBarItem_[a-z0-9]+"/)[0].exports; 11 - 12 - const MODULE_REGEX = /Webpack-Module-(\d+)/g; 13 14 const logger = moonlight.getLogger("moonbase/crashScreen"); 15 ··· 87 } 88 89 function ExtensionDisableCard({ ext }: { ext: DetectedExtension }) { 90 - function disableWithDependents() { 91 const disable = new Set<string>(); 92 disable.add(ext.id); 93 for (const [id, dependencies] of moonlightNode.processedExtensions.dependencyGraph) { ··· 108 msg += "?"; 109 110 if (confirm(msg)) { 111 - moonlightNode.writeConfig(config); 112 window.location.reload(); 113 } 114 } ··· 142 const causes = React.useMemo(() => { 143 const causes = new Set<string>(); 144 if (state.error.stack) { 145 - for (const [, id] of state.error.stack.matchAll(MODULE_REGEX)) 146 for (const ext of moonlight.patched.get(id) ?? []) causes.add(ext); 147 } 148 - for (const [, id] of state.info.componentStack.matchAll(MODULE_REGEX)) 149 for (const ext of moonlight.patched.get(id) ?? []) causes.add(ext); 150 return [...causes]; 151 }, []); 152 ··· 154 <div className="moonbase-crash-wrapper"> 155 {action} 156 <TabBar 157 - className={`${TabBarClasses.tabBar} moonbase-crash-tabs`} 158 type="top" 159 selectedItem={tab} 160 onItemSelect={(v) => setTab(v)} 161 > 162 - <TabBar.Item className={TabBarClasses.tabBarItem} id="crash"> 163 Crash details 164 </TabBar.Item> 165 - <TabBar.Item className={TabBarClasses.tabBarItem} id="extensions" disabled={updateCount === 0}> 166 {`Extension updates (${updateCount})`} 167 </TabBar.Item> 168 - <TabBar.Item className={TabBarClasses.tabBarItem} id="causes" disabled={causes.length === 0}> 169 {`Possible causes (${causes.length})`} 170 </TabBar.Item> 171 </TabBar>
··· 1 import React from "@moonlight-mod/wp/react"; 2 + import { Button, TabBar } from "@moonlight-mod/wp/discord/components/common/index"; 3 import { useStateFromStores, useStateFromStoresObject } from "@moonlight-mod/wp/discord/packages/flux"; 4 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 5 import { RepositoryManifest, UpdateState } from "../types"; 6 import { ConfigExtension, DetectedExtension } from "@moonlight-mod/types"; 7 + import DiscoveryClasses from "@moonlight-mod/wp/discord/modules/discovery/web/Discovery.css"; 8 9 + const MODULE_REGEX = /Webpack-Module\/(\d+)\/(\d+)/g; 10 11 const logger = moonlight.getLogger("moonbase/crashScreen"); 12 ··· 84 } 85 86 function ExtensionDisableCard({ ext }: { ext: DetectedExtension }) { 87 + async function disableWithDependents() { 88 const disable = new Set<string>(); 89 disable.add(ext.id); 90 for (const [id, dependencies] of moonlightNode.processedExtensions.dependencyGraph) { ··· 105 msg += "?"; 106 107 if (confirm(msg)) { 108 + await moonlightNode.writeConfig(config); 109 window.location.reload(); 110 } 111 } ··· 139 const causes = React.useMemo(() => { 140 const causes = new Set<string>(); 141 if (state.error.stack) { 142 + for (const [, , id] of state.error.stack.matchAll(MODULE_REGEX)) 143 for (const ext of moonlight.patched.get(id) ?? []) causes.add(ext); 144 } 145 + for (const [, , id] of state.info.componentStack.matchAll(MODULE_REGEX)) 146 for (const ext of moonlight.patched.get(id) ?? []) causes.add(ext); 147 + 148 + for (const [path, id] of Object.entries(moonlight.moonmap.modules)) { 149 + const MAPPING_REGEX = new RegExp( 150 + // @ts-expect-error Only Firefox has RegExp.escape 151 + `(${RegExp.escape ? RegExp.escape(path) : path.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})`, 152 + "g" 153 + ); 154 + 155 + if (state.error.stack) { 156 + for (const match of state.error.stack.matchAll(MAPPING_REGEX)) 157 + if (match) for (const ext of moonlight.patched.get(id) ?? []) causes.add(ext); 158 + } 159 + for (const match of state.info.componentStack.matchAll(MAPPING_REGEX)) 160 + if (match) for (const ext of moonlight.patched.get(id) ?? []) causes.add(ext); 161 + } 162 + 163 return [...causes]; 164 }, []); 165 ··· 167 <div className="moonbase-crash-wrapper"> 168 {action} 169 <TabBar 170 + className={`${DiscoveryClasses.tabBar} moonbase-crash-tabs`} 171 type="top" 172 selectedItem={tab} 173 onItemSelect={(v) => setTab(v)} 174 > 175 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id="crash"> 176 Crash details 177 </TabBar.Item> 178 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id="extensions" disabled={updateCount === 0}> 179 {`Extension updates (${updateCount})`} 180 </TabBar.Item> 181 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id="causes" disabled={causes.length === 0}> 182 {`Possible causes (${causes.length})`} 183 </TabBar.Item> 184 </TabBar>
+27 -17
packages/core-extensions/src/moonbase/webpackModules/settings.tsx
··· 2 import React from "@moonlight-mod/wp/react"; 3 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 4 import { Moonbase, pages, RestartAdviceMessage, Update } from "@moonlight-mod/wp/moonbase_ui"; 5 - 6 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 7 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 8 - 9 - const { MenuItem, Text, Breadcrumbs } = Components; 10 - 11 - const Margins = spacepack.require("discord/styles/shared/Margins.css"); 12 - 13 - const { open } = spacepack.findByCode(':"USER_SETTINGS_MODAL_SET_SECTION"')[0].exports.Z; 14 15 - let SettingsNotice; 16 const notice = { 17 stores: [MoonbaseSettingsStore], 18 element: () => { 19 // Require it here because lazy loading SUX 20 - SettingsNotice ??= spacepack.findByCode("onSaveButtonColor", "FocusRingScope")[0].exports.Z; 21 return ( 22 <SettingsNotice 23 submitting={MoonbaseSettingsStore.submitting} 24 onReset={() => { 25 MoonbaseSettingsStore.reset(); 26 }} 27 - onSave={() => { 28 - MoonbaseSettingsStore.writeConfig(); 29 }} 30 /> 31 ); 32 } 33 }; 34 35 function addSection(id: string, name: string, element: React.FunctionComponent) { 36 - settings.addSection(`moonbase-${id}`, name, element, null, -2, notice); 37 } 38 39 // FIXME: move to component types ··· 50 ); 51 } 52 53 if (MoonbaseSettingsStore.getExtensionConfigRaw<boolean>("moonbase", "sections", false)) { 54 - settings.addHeader("Moonbase", -2); 55 56 - for (const page of pages) { 57 addSection(page.id, page.name, () => { 58 const breadcrumbs = [ 59 { id: "moonbase", label: "Moonbase" }, ··· 78 ); 79 }); 80 } 81 } else { 82 - settings.addSection("moonbase", "Moonbase", Moonbase, null, -2, notice); 83 84 settings.addSectionMenuItems( 85 "moonbase", 86 ...pages.map((page, i) => ( 87 - <MenuItem key={page.id} id={`moonbase-${page.id}`} label={page.name} action={() => open("moonbase", i)} /> 88 )) 89 ); 90 }
··· 2 import React from "@moonlight-mod/wp/react"; 3 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 4 import { Moonbase, pages, RestartAdviceMessage, Update } from "@moonlight-mod/wp/moonbase_ui"; 5 + import UserSettingsModalActionCreators from "@moonlight-mod/wp/discord/actions/UserSettingsModalActionCreators"; 6 + import Margins from "@moonlight-mod/wp/discord/styles/shared/Margins.css"; 7 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 8 + import { Text, Breadcrumbs } from "@moonlight-mod/wp/discord/components/common/index"; 9 + import { MenuItem } from "@moonlight-mod/wp/contextMenu_contextMenu"; 10 11 const notice = { 12 stores: [MoonbaseSettingsStore], 13 element: () => { 14 // Require it here because lazy loading SUX 15 + const SettingsNotice = spacepack.require("discord/components/common/SettingsNotice").default; 16 return ( 17 <SettingsNotice 18 submitting={MoonbaseSettingsStore.submitting} 19 onReset={() => { 20 MoonbaseSettingsStore.reset(); 21 }} 22 + onSave={async () => { 23 + await MoonbaseSettingsStore.writeConfig(); 24 }} 25 /> 26 ); 27 } 28 }; 29 + 30 + const oldLocation = MoonbaseSettingsStore.getExtensionConfigRaw<boolean>("moonbase", "oldLocation", false); 31 + const position = oldLocation ? -2 : -9999; 32 33 function addSection(id: string, name: string, element: React.FunctionComponent) { 34 + settings.addSection(`moonbase-${id}`, name, element, null, position, notice); 35 } 36 37 // FIXME: move to component types ··· 48 ); 49 } 50 51 + if (!oldLocation) { 52 + settings.addDivider(position); 53 + } 54 + 55 if (MoonbaseSettingsStore.getExtensionConfigRaw<boolean>("moonbase", "sections", false)) { 56 + if (oldLocation) settings.addHeader("Moonbase", position); 57 58 + const _pages = oldLocation ? pages : pages.reverse(); 59 + for (const page of _pages) { 60 addSection(page.id, page.name, () => { 61 const breadcrumbs = [ 62 { id: "moonbase", label: "Moonbase" }, ··· 81 ); 82 }); 83 } 84 + 85 + if (!oldLocation) settings.addHeader("Moonbase", position); 86 } else { 87 + settings.addSection("moonbase", "Moonbase", Moonbase, null, position, notice); 88 89 settings.addSectionMenuItems( 90 "moonbase", 91 ...pages.map((page, i) => ( 92 + <MenuItem 93 + key={page.id} 94 + id={`moonbase-${page.id}`} 95 + label={page.name} 96 + action={() => UserSettingsModalActionCreators.open("moonbase", i.toString())} 97 + /> 98 )) 99 ); 100 }
+83 -22
packages/core-extensions/src/moonbase/webpackModules/stores.ts
··· 1 import { Config, ExtensionEnvironment, ExtensionLoadSource, ExtensionSettingsAdvice } from "@moonlight-mod/types"; 2 - import { ExtensionState, MoonbaseExtension, MoonbaseNatives, RepositoryManifest, RestartAdvice } from "../types"; 3 import { Store } from "@moonlight-mod/wp/discord/packages/flux"; 4 import Dispatcher from "@moonlight-mod/wp/discord/Dispatcher"; 5 import getNatives from "../native"; 6 import { mainRepo } from "@moonlight-mod/types/constants"; 7 import { checkExtensionCompat, ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 8 import { CustomComponent } from "@moonlight-mod/types/coreExtensions/moonbase"; 9 import { getConfigOption, setConfigOption } from "@moonlight-mod/core/util/config"; 10 import diff from "microdiff"; 11 ··· 25 submitting: boolean; 26 installing: boolean; 27 28 newVersion: string | null; 29 shouldShowNotice: boolean; 30 31 - #showOnlyUpdateable = false; 32 - set showOnlyUpdateable(v: boolean) { 33 - this.#showOnlyUpdateable = v; 34 - this.emitChange(); 35 - } 36 - get showOnlyUpdateable() { 37 - return this.#showOnlyUpdateable; 38 - } 39 - 40 restartAdvice = RestartAdvice.NotNeeded; 41 42 extensions: { [id: number]: MoonbaseExtension }; ··· 76 }; 77 } 78 79 this.checkUpdates(); 80 } 81 82 async checkUpdates() { ··· 237 let val = this.config.extensions[ext.id]; 238 239 if (val == null) { 240 - this.config.extensions[ext.id] = { enabled }; 241 this.modified = this.isModified(); 242 this.emitChange(); 243 return; ··· 254 this.emitChange(); 255 } 256 257 async installExtension(uniqueId: number) { 258 const ext = this.getExtension(uniqueId); 259 if (!("download" in ext.manifest)) { ··· 274 existing.settingsOverride = update.updateManifest.settings; 275 existing.compat = checkExtensionCompat(update.updateManifest); 276 existing.manifest = update.updateManifest; 277 - existing.hasUpdate = false; 278 existing.changelog = update.updateManifest.meta?.changelog; 279 } 280 ··· 346 } 347 348 async updateMoonlight() { 349 - await natives.updateMoonlight(); 350 } 351 352 getConfigOption<K extends keyof Config>(key: K): Config[K] { ··· 374 } 375 376 #computeRestartAdvice() { 377 const i = this.initialConfig; // Initial config, from startup 378 const n = this.config; // New config about to be saved 379 ··· 403 // If it's enabled but not detected yet, restart. 404 if (newEnabled && !detected) { 405 return updateAdvice(RestartAdvice.RestartNeeded); 406 - continue; 407 } 408 409 // Toggling extensions specifically wants to rely on the initial state, ··· 431 } 432 } 433 434 - const initConfig = typeof initState === "boolean" ? {} : initState.config ?? {}; 435 - const newConfig = typeof newState === "boolean" ? {} : newState.config ?? {}; 436 437 const def = ext.manifest.settings; 438 if (!def) continue; 439 440 const changedKeys = diff(initConfig, newConfig, { cyclesFix: false }).map((c) => c.path[0]); 441 for (const key in def) { 442 if (!changedKeys.includes(key)) continue; ··· 461 return returnedAdvice; 462 } 463 464 - writeConfig() { 465 - this.submitting = true; 466 - this.restartAdvice = this.#computeRestartAdvice(); 467 468 - moonlightNode.writeConfig(this.config); 469 - this.savedConfig = this.clone(this.config); 470 471 - this.submitting = false; 472 this.modified = false; 473 this.emitChange(); 474 } 475
··· 1 import { Config, ExtensionEnvironment, ExtensionLoadSource, ExtensionSettingsAdvice } from "@moonlight-mod/types"; 2 + import { 3 + ExtensionState, 4 + MoonbaseExtension, 5 + MoonbaseNatives, 6 + RepositoryManifest, 7 + RestartAdvice, 8 + UpdateState 9 + } from "../types"; 10 import { Store } from "@moonlight-mod/wp/discord/packages/flux"; 11 import Dispatcher from "@moonlight-mod/wp/discord/Dispatcher"; 12 import getNatives from "../native"; 13 import { mainRepo } from "@moonlight-mod/types/constants"; 14 import { checkExtensionCompat, ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 15 import { CustomComponent } from "@moonlight-mod/types/coreExtensions/moonbase"; 16 + import { NodeEventType } from "@moonlight-mod/types/core/event"; 17 import { getConfigOption, setConfigOption } from "@moonlight-mod/core/util/config"; 18 import diff from "microdiff"; 19 ··· 33 submitting: boolean; 34 installing: boolean; 35 36 + #updateState = UpdateState.Ready; 37 + get updateState() { 38 + return this.#updateState; 39 + } 40 newVersion: string | null; 41 shouldShowNotice: boolean; 42 43 restartAdvice = RestartAdvice.NotNeeded; 44 45 extensions: { [id: number]: MoonbaseExtension }; ··· 79 }; 80 } 81 82 + // This is async but we're calling it without 83 this.checkUpdates(); 84 + 85 + // Update our state if another extension edited the config programatically 86 + moonlightNode.events.addEventListener(NodeEventType.ConfigSaved, (config) => { 87 + if (!this.submitting) { 88 + this.config = this.clone(config); 89 + // NOTE: This is also async but we're calling it without 90 + this.processConfigChanged(); 91 + } 92 + }); 93 } 94 95 async checkUpdates() { ··· 250 let val = this.config.extensions[ext.id]; 251 252 if (val == null) { 253 + this.config.extensions[ext.id] = enabled; 254 this.modified = this.isModified(); 255 this.emitChange(); 256 return; ··· 267 this.emitChange(); 268 } 269 270 + dismissAllExtensionUpdates() { 271 + for (const id in this.extensions) { 272 + this.extensions[id].hasUpdate = false; 273 + } 274 + this.emitChange(); 275 + } 276 + 277 + async updateAllExtensions() { 278 + for (const id of Object.keys(this.updates)) { 279 + try { 280 + await this.installExtension(parseInt(id)); 281 + } catch (e) { 282 + logger.error("Error bulk updating extension", id, e); 283 + } 284 + } 285 + } 286 + 287 async installExtension(uniqueId: number) { 288 const ext = this.getExtension(uniqueId); 289 if (!("download" in ext.manifest)) { ··· 304 existing.settingsOverride = update.updateManifest.settings; 305 existing.compat = checkExtensionCompat(update.updateManifest); 306 existing.manifest = update.updateManifest; 307 existing.changelog = update.updateManifest.meta?.changelog; 308 } 309 ··· 375 } 376 377 async updateMoonlight() { 378 + this.#updateState = UpdateState.Working; 379 + this.emitChange(); 380 + 381 + await natives 382 + .updateMoonlight() 383 + .then(() => (this.#updateState = UpdateState.Installed)) 384 + .catch((e) => { 385 + logger.error(e); 386 + this.#updateState = UpdateState.Failed; 387 + }); 388 + 389 + this.emitChange(); 390 } 391 392 getConfigOption<K extends keyof Config>(key: K): Config[K] { ··· 414 } 415 416 #computeRestartAdvice() { 417 + // If moonlight update needs a restart, always hide advice. 418 + if (this.#updateState === UpdateState.Installed) return RestartAdvice.NotNeeded; 419 + 420 const i = this.initialConfig; // Initial config, from startup 421 const n = this.config; // New config about to be saved 422 ··· 446 // If it's enabled but not detected yet, restart. 447 if (newEnabled && !detected) { 448 return updateAdvice(RestartAdvice.RestartNeeded); 449 } 450 451 // Toggling extensions specifically wants to rely on the initial state, ··· 473 } 474 } 475 476 + const initConfig = typeof initState === "boolean" ? {} : { ...initState?.config }; 477 + const newConfig = typeof newState === "boolean" ? {} : { ...newState?.config }; 478 479 const def = ext.manifest.settings; 480 if (!def) continue; 481 482 + for (const key in def) { 483 + const defaultValue = def[key].default; 484 + 485 + initConfig[key] ??= defaultValue; 486 + newConfig[key] ??= defaultValue; 487 + } 488 + 489 const changedKeys = diff(initConfig, newConfig, { cyclesFix: false }).map((c) => c.path[0]); 490 for (const key in def) { 491 if (!changedKeys.includes(key)) continue; ··· 510 return returnedAdvice; 511 } 512 513 + async writeConfig() { 514 + try { 515 + this.submitting = true; 516 + this.emitChange(); 517 518 + await moonlightNode.writeConfig(this.config); 519 + await this.processConfigChanged(); 520 + } finally { 521 + this.submitting = false; 522 + this.emitChange(); 523 + } 524 + } 525 526 + private async processConfigChanged() { 527 + this.savedConfig = this.clone(this.config); 528 + this.restartAdvice = this.#computeRestartAdvice(); 529 this.modified = false; 530 + 531 + const modifiedRepos = diff(this.savedConfig.repositories, this.config.repositories); 532 + if (modifiedRepos.length !== 0) await this.checkUpdates(); 533 + 534 this.emitChange(); 535 } 536
+2 -4
packages/core-extensions/src/moonbase/webpackModules/ui/HelpMessage.tsx
··· 1 import React from "@moonlight-mod/wp/react"; 2 - import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 3 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 4 import { Text } from "@moonlight-mod/wp/discord/components/common/index"; 5 - 6 - const Margins = spacepack.require("discord/styles/shared/Margins.css"); 7 - const HelpMessageClasses = spacepack.findByCode("positive:", "iconDiv:")[0].exports; 8 9 // reimpl of HelpMessage but with a custom icon 10 export default function HelpMessage({
··· 1 import React from "@moonlight-mod/wp/react"; 2 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 3 import { Text } from "@moonlight-mod/wp/discord/components/common/index"; 4 + import HelpMessageClasses from "@moonlight-mod/wp/discord/components/common/HelpMessage.css"; 5 + import Margins from "@moonlight-mod/wp/discord/styles/shared/Margins.css"; 6 7 // reimpl of HelpMessage but with a custom icon 8 export default function HelpMessage({
+1 -5
packages/core-extensions/src/moonbase/webpackModules/ui/RestartAdvice.tsx
··· 1 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 2 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 3 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 4 import React from "@moonlight-mod/wp/react"; 5 import { RestartAdvice } from "../../types"; 6 import HelpMessage from "./HelpMessage"; 7 - 8 - const { Button } = Components; 9 10 const strings: Record<RestartAdvice, string> = { 11 [RestartAdvice.NotNeeded]: "how did you even", ··· 27 [RestartAdvice.ReloadNeeded]: () => window.location.reload(), 28 [RestartAdvice.RestartNeeded]: () => MoonbaseSettingsStore.restartDiscord() 29 }; 30 - 31 - const { CircleWarningIcon } = Components; 32 33 export default function RestartAdviceMessage() { 34 const restartAdvice = useStateFromStores([MoonbaseSettingsStore], () => MoonbaseSettingsStore.restartAdvice);
··· 1 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 2 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 3 + import { Button, CircleWarningIcon } from "@moonlight-mod/wp/discord/components/common/index"; 4 import React from "@moonlight-mod/wp/react"; 5 import { RestartAdvice } from "../../types"; 6 import HelpMessage from "./HelpMessage"; 7 8 const strings: Record<RestartAdvice, string> = { 9 [RestartAdvice.NotNeeded]: "how did you even", ··· 25 [RestartAdvice.ReloadNeeded]: () => window.location.reload(), 26 [RestartAdvice.RestartNeeded]: () => MoonbaseSettingsStore.restartDiscord() 27 }; 28 29 export default function RestartAdviceMessage() { 30 const restartAdvice = useStateFromStores([MoonbaseSettingsStore], () => MoonbaseSettingsStore.restartAdvice);
+110
packages/core-extensions/src/moonbase/webpackModules/ui/about.tsx
···
··· 1 + import { 2 + Text, 3 + useThemeContext, 4 + Button, 5 + AngleBracketsIcon, 6 + BookCheckIcon, 7 + ClydeIcon 8 + } from "@moonlight-mod/wp/discord/components/common/index"; 9 + import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 10 + import React from "@moonlight-mod/wp/react"; 11 + import MarkupUtils from "@moonlight-mod/wp/discord/modules/markup/MarkupUtils"; 12 + import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 13 + 14 + const wordmark = "https://raw.githubusercontent.com/moonlight-mod/moonlight/refs/heads/main/img/wordmark.png"; 15 + const wordmarkLight = 16 + "https://raw.githubusercontent.com/moonlight-mod/moonlight/refs/heads/main/img/wordmark-light.png"; 17 + 18 + function parse(str: string) { 19 + return MarkupUtils.parse(str, true, { 20 + allowHeading: true, 21 + allowLinks: true, 22 + allowList: true 23 + }); 24 + } 25 + 26 + function Dev({ name, picture, link }: { name: string; picture: string; link: string }) { 27 + return ( 28 + <Button onClick={() => window.open(link)} color={Button.Colors.PRIMARY} className="moonbase-dev"> 29 + <Flex direction={Flex.Direction.HORIZONTAL} align={Flex.Align.CENTER} className="moonbase-gap"> 30 + <img src={picture} alt={name} className="moonbase-dev-avatar" /> 31 + 32 + <Text variant="text-md/semibold">{name}</Text> 33 + </Flex> 34 + </Button> 35 + ); 36 + } 37 + 38 + function IconButton({ 39 + text, 40 + link, 41 + icon, 42 + openInClient 43 + }: { 44 + text: string; 45 + link: string; 46 + icon: React.FC<any>; 47 + openInClient?: boolean; 48 + }) { 49 + return ( 50 + <Button 51 + onClick={() => { 52 + if (openInClient) { 53 + try { 54 + const { handleClick } = spacepack.require("discord/utils/MaskedLinkUtils"); 55 + handleClick({ href: link }); 56 + } catch { 57 + window.open(link); 58 + } 59 + } else { 60 + // Will open externally in the user's browser 61 + window.open(link); 62 + } 63 + }} 64 + > 65 + <Flex direction={Flex.Direction.HORIZONTAL} align={Flex.Align.CENTER} className="moonbase-gap"> 66 + {React.createElement(icon, { 67 + size: "sm", 68 + color: "currentColor" 69 + })} 70 + {text} 71 + </Flex> 72 + </Button> 73 + ); 74 + } 75 + 76 + export default function AboutPage() { 77 + const darkTheme = useThemeContext()?.theme !== "light"; 78 + 79 + return ( 80 + <Flex direction={Flex.Direction.VERTICAL} align={Flex.Align.CENTER} className="moonbase-about-page"> 81 + <img src={darkTheme ? wordmarkLight : wordmark} alt="moonlight wordmark" className="moonbase-wordmark" /> 82 + 83 + <Text variant="heading-lg/medium">created by:</Text> 84 + <div className="moonbase-devs"> 85 + <Dev name="Cynosphere" picture="https://github.com/Cynosphere.png" link="https://github.com/Cynosphere" /> 86 + <Dev name="NotNite" picture="https://github.com/NotNite.png" link="https://github.com/NotNite" /> 87 + <Dev name="adryd" picture="https://github.com/adryd325.png" link="https://github.com/adryd325" /> 88 + <Dev name="redstonekasi" picture="https://github.com/redstonekasi.png" link="https://github.com/redstonekasi" /> 89 + </div> 90 + 91 + <Flex direction={Flex.Direction.HORIZONTAL} align={Flex.Align.CENTER} className="moonbase-gap"> 92 + <IconButton text="View source" icon={AngleBracketsIcon} link="https://github.com/moonlight-mod/moonlight" /> 93 + <IconButton text="Open the docs" icon={BookCheckIcon} link="https://moonlight-mod.github.io/" /> 94 + <IconButton text="Join the server" icon={ClydeIcon} link="https://discord.gg/FdZBTFCP6F" openInClient={true} /> 95 + </Flex> 96 + 97 + <Flex direction={Flex.Direction.VERTICAL} align={Flex.Align.START}> 98 + <Text variant="text-sm/normal"> 99 + {parse(`moonlight \`${window.moonlight.version}\` on \`${window.moonlight.branch}\``)} 100 + </Text> 101 + 102 + <Text variant="text-sm/normal"> 103 + {parse( 104 + "moonlight is licensed under the [GNU Lesser General Public License](https://www.gnu.org/licenses/lgpl-3.0.html) (`LGPL-3.0-or-later`)." 105 + )} 106 + </Text> 107 + </Flex> 108 + </Flex> 109 + ); 110 + }
+14 -13
packages/core-extensions/src/moonbase/webpackModules/ui/config/index.tsx
··· 16 Clickable 17 } from "@moonlight-mod/wp/discord/components/common/index"; 18 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 19 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 20 21 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 22 23 - const FormClasses = spacepack.findByCode("dividerDefault:")[0].exports; 24 - const Margins = spacepack.findByCode("marginCenterHorz:")[0].exports; 25 - 26 - let RemoveButtonClasses: any; 27 spacepack 28 .lazyLoad( 29 "renderArtisanalHack", 30 /\[(?:.\.e\("\d+?"\),?)+\][^}]+?webpackId:\d+,name:"GuildSettings"/, 31 /webpackId:(\d+),name:"GuildSettings"/ 32 ) 33 - .then(() => (RemoveButtonClasses = spacepack.findByCode("removeButtonContainer")[0].exports)); 34 - 35 - // FIXME: type component keys 36 - const { CircleXIcon } = Components; 37 38 function RemoveEntryButton({ onClick }: { onClick: () => void }) { 39 return ( 40 - <div className={RemoveButtonClasses.removeButtonContainer}> 41 <Tooltip text="Remove entry" position="top"> 42 {(props: any) => ( 43 - <Clickable {...props} className={RemoveButtonClasses.removeButton} onClick={onClick}> 44 <CircleXIcon width={24} height={24} /> 45 </Clickable> 46 )} ··· 121 <FormText className={Margins.marginBottom4}>A list of remote repositories to display extensions from</FormText> 122 <ArrayFormItem config="repositories" /> 123 </FormItem> 124 - <FormDivider className={FormClasses.dividerDefault} /> 125 <FormItem title="Extension search paths" className={Margins.marginTop20}> 126 <FormText className={Margins.marginBottom4}> 127 A list of local directories to search for built extensions 128 </FormText> 129 <ArrayFormItem config="devSearchPaths" /> 130 </FormItem> 131 - <FormDivider className={FormClasses.dividerDefault} /> 132 <FormSwitch 133 className={Margins.marginTop20} 134 value={MoonbaseSettingsStore.getConfigOption("patchAll") ?? false}
··· 16 Clickable 17 } from "@moonlight-mod/wp/discord/components/common/index"; 18 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 19 + import { CircleXIcon } from "@moonlight-mod/wp/discord/components/common/index"; 20 + import Margins from "@moonlight-mod/wp/discord/styles/shared/Margins.css"; 21 + import FormSwitchClasses from "@moonlight-mod/wp/discord/components/common/FormSwitch.css"; 22 23 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 24 25 + let GuildSettingsRoleEditClasses: any; 26 spacepack 27 .lazyLoad( 28 "renderArtisanalHack", 29 /\[(?:.\.e\("\d+?"\),?)+\][^}]+?webpackId:\d+,name:"GuildSettings"/, 30 /webpackId:(\d+),name:"GuildSettings"/ 31 ) 32 + .then( 33 + () => 34 + (GuildSettingsRoleEditClasses = spacepack.require( 35 + "discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css" 36 + )) 37 + ); 38 39 function RemoveEntryButton({ onClick }: { onClick: () => void }) { 40 return ( 41 + <div className={GuildSettingsRoleEditClasses.removeButtonContainer}> 42 <Tooltip text="Remove entry" position="top"> 43 {(props: any) => ( 44 + <Clickable {...props} className={GuildSettingsRoleEditClasses.removeButton} onClick={onClick}> 45 <CircleXIcon width={24} height={24} /> 46 </Clickable> 47 )} ··· 122 <FormText className={Margins.marginBottom4}>A list of remote repositories to display extensions from</FormText> 123 <ArrayFormItem config="repositories" /> 124 </FormItem> 125 + <FormDivider className={FormSwitchClasses.dividerDefault} /> 126 <FormItem title="Extension search paths" className={Margins.marginTop20}> 127 <FormText className={Margins.marginBottom4}> 128 A list of local directories to search for built extensions 129 </FormText> 130 <ArrayFormItem config="devSearchPaths" /> 131 </FormItem> 132 + <FormDivider className={FormSwitchClasses.dividerDefault} /> 133 <FormSwitch 134 className={Margins.marginTop20} 135 value={MoonbaseSettingsStore.getConfigOption("patchAll") ?? false}
+138 -75
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/card.tsx
··· 1 import { ExtensionState } from "../../../types"; 2 import { constants, ExtensionLoadSource, ExtensionTag } from "@moonlight-mod/types"; 3 import { ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 4 - 5 - import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 6 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 7 import React from "@moonlight-mod/wp/react"; 8 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 9 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 10 import MarkupUtils from "@moonlight-mod/wp/discord/modules/markup/MarkupUtils"; 11 - import IntegrationCard from "@moonlight-mod/wp/discord/modules/guild_settings/IntegrationCard.css"; 12 - 13 import ExtensionInfo from "./info"; 14 import Settings from "./settings"; 15 import { doGenericExtensionPopup, doMissingExtensionPopup } from "./popup"; ··· 21 Settings 22 } 23 24 - import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 25 - 26 - const { BeakerIcon, DownloadIcon, TrashIcon, AngleBracketsIcon, Tooltip } = Components; 27 - 28 - const PanelButton = spacepack.findByCode("Masks.PANEL_BUTTON")[0].exports.Z; 29 - const TabBarClasses = spacepack.findByCode("tabBar:", "tabBarItem:", "headerContentWrapper:")[0].exports; 30 - const MarkupClasses = spacepack.findByCode("markup:", "inlineFormat:")[0].exports; 31 - 32 - const BuildOverrideClasses = spacepack.findByCode("disabledButtonOverride:")[0].exports; 33 - 34 const COMPAT_TEXT_MAP: Record<ExtensionCompat, string> = { 35 [ExtensionCompat.Compatible]: "huh?", 36 [ExtensionCompat.InvalidApiLevel]: "Incompatible API level", ··· 38 }; 39 const CONFLICTING_TEXT = "This extension is already installed from another source."; 40 41 - export default function ExtensionCard({ uniqueId }: { uniqueId: number }) { 42 - const [tab, setTab] = React.useState(ExtensionPage.Info); 43 44 const { ext, enabled, busy, update, conflicting } = useStateFromStores([MoonbaseSettingsStore], () => { 45 return { 46 ext: MoonbaseSettingsStore.getExtension(uniqueId), ··· 51 }; 52 }); 53 54 - // Why it work like that :sob: 55 - if (ext == null) return <></>; 56 - 57 - const { Card, Text, FormSwitch, TabBar, Button } = Components; 58 59 const tagline = ext.manifest?.meta?.tagline; 60 const settings = ext.settingsOverride ?? ext.manifest?.settings; 61 const description = ext.manifest?.meta?.description; 62 const changelog = ext.changelog; 63 const enabledDependants = useStateFromStores([MoonbaseSettingsStore], () => 64 Object.keys(MoonbaseSettingsStore.extensions) 65 .filter((uniqueId) => { 66 const potentialDependant = MoonbaseSettingsStore.getExtension(parseInt(uniqueId)); 67 68 return ( 69 - potentialDependant.manifest.dependencies?.includes(ext.id) && 70 MoonbaseSettingsStore.getExtensionEnabled(parseInt(uniqueId)) 71 ); 72 }) ··· 74 ); 75 const implicitlyEnabled = enabledDependants.length > 0; 76 77 - return ( 78 - <Card editable={true} className={IntegrationCard.card}> 79 - <div className={IntegrationCard.cardHeader}> 80 <Flex direction={Flex.Direction.VERTICAL}> 81 <Flex direction={Flex.Direction.HORIZONTAL} align={Flex.Align.CENTER}> 82 <Text variant="text-md/semibold">{ext.manifest?.meta?.name ?? ext.id}</Text> 83 {ext.source.type === ExtensionLoadSource.Developer && ( 84 <Tooltip text="This is a local extension" position="top"> 85 - {(props: any) => <BeakerIcon {...props} class={BuildOverrideClasses.infoIcon} size="xs" />} 86 </Tooltip> 87 )} 88 </Flex> ··· 99 gap: "1rem" 100 }} 101 > 102 - {ext.manifest.meta?.source != null && ( 103 - <PanelButton 104 - icon={AngleBracketsIcon} 105 - tooltipText="View source" 106 - onClick={() => { 107 - window.open(ext.manifest.meta!.source); 108 - }} 109 - /> 110 - )} 111 - 112 {ext.state === ExtensionState.NotDownloaded ? ( 113 <Tooltip 114 text={conflicting ? CONFLICTING_TEXT : COMPAT_TEXT_MAP[ext.compat]} ··· 164 disabled={implicitlyEnabled || ext.compat !== ExtensionCompat.Compatible} 165 hideBorder={true} 166 style={{ marginBottom: "0px" }} 167 tooltipNote={ 168 - ext.compat !== ExtensionCompat.Compatible 169 - ? COMPAT_TEXT_MAP[ext.compat] 170 - : implicitlyEnabled 171 - ? `This extension is a dependency of the following enabled extension${ 172 - enabledDependants.length > 1 ? "s" : "" 173 - }: ${enabledDependants.map((a) => a.manifest.meta?.name ?? a.id).join(", ")}` 174 - : undefined 175 } 176 onChange={() => { 177 const toggle = () => { ··· 204 </div> 205 206 <div> 207 - {(description != null || changelog != null || settings != null) && ( 208 - <TabBar 209 - selectedItem={tab} 210 - type="top" 211 - onItemSelect={setTab} 212 - className={TabBarClasses.tabBar} 213 - style={{ 214 - padding: "0 20px" 215 - }} 216 - > 217 - <TabBar.Item className={TabBarClasses.tabBarItem} id={ExtensionPage.Info}> 218 - Info 219 - </TabBar.Item> 220 - 221 - {description != null && ( 222 - <TabBar.Item className={TabBarClasses.tabBarItem} id={ExtensionPage.Description}> 223 - Description 224 </TabBar.Item> 225 - )} 226 227 - {changelog != null && ( 228 - <TabBar.Item className={TabBarClasses.tabBarItem} id={ExtensionPage.Changelog}> 229 - Changelog 230 - </TabBar.Item> 231 - )} 232 233 - {settings != null && ( 234 - <TabBar.Item className={TabBarClasses.tabBarItem} id={ExtensionPage.Settings}> 235 - Settings 236 - </TabBar.Item> 237 - )} 238 - </TabBar> 239 )} 240 241 <Flex 242 justify={Flex.Justify.START} 243 wrap={Flex.Wrap.WRAP} 244 style={{ 245 - padding: "16px 16px" 246 }} 247 > 248 - {tab === ExtensionPage.Info && <ExtensionInfo ext={ext} />} 249 {tab === ExtensionPage.Description && ( 250 <Text variant="text-md/normal" className={MarkupClasses.markup} style={{ width: "100%" }}> 251 {MarkupUtils.parse(description ?? "*No description*", true, { ··· 264 })} 265 </Text> 266 )} 267 - {tab === ExtensionPage.Settings && <Settings ext={ext} />} 268 </Flex> 269 </div> 270 </Card>
··· 1 import { ExtensionState } from "../../../types"; 2 import { constants, ExtensionLoadSource, ExtensionTag } from "@moonlight-mod/types"; 3 + 4 import { ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 5 + import { 6 + ScienceIcon, 7 + DownloadIcon, 8 + TrashIcon, 9 + AngleBracketsIcon, 10 + Tooltip, 11 + Card, 12 + Text, 13 + FormSwitch, 14 + TabBar, 15 + Button, 16 + ChannelListIcon, 17 + HeartIcon, 18 + WindowTopOutlineIcon, 19 + WarningIcon 20 + } from "@moonlight-mod/wp/discord/components/common/index"; 21 import React from "@moonlight-mod/wp/react"; 22 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 23 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 24 import MarkupUtils from "@moonlight-mod/wp/discord/modules/markup/MarkupUtils"; 25 + import AppCardClasses from "@moonlight-mod/wp/discord/modules/guild_settings/web/AppCard.css"; 26 + import PanelButton from "@moonlight-mod/wp/discord/components/common/PanelButton"; 27 + import DiscoveryClasses from "@moonlight-mod/wp/discord/modules/discovery/web/Discovery.css"; 28 + import MarkupClasses from "@moonlight-mod/wp/discord/modules/messages/web/Markup.css"; 29 + import BuildOverrideClasses from "@moonlight-mod/wp/discord/modules/build_overrides/web/BuildOverride.css"; 30 + import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 31 + import ErrorBoundary from "@moonlight-mod/wp/common_ErrorBoundary"; 32 import ExtensionInfo from "./info"; 33 import Settings from "./settings"; 34 import { doGenericExtensionPopup, doMissingExtensionPopup } from "./popup"; ··· 40 Settings 41 } 42 43 const COMPAT_TEXT_MAP: Record<ExtensionCompat, string> = { 44 [ExtensionCompat.Compatible]: "huh?", 45 [ExtensionCompat.InvalidApiLevel]: "Incompatible API level", ··· 47 }; 48 const CONFLICTING_TEXT = "This extension is already installed from another source."; 49 50 + function PanelLinkButton({ icon, tooltip, link }: { icon: React.ReactNode; tooltip: string; link: string }) { 51 + return ( 52 + <PanelButton 53 + icon={icon} 54 + tooltipText={tooltip} 55 + onClick={() => { 56 + window.open(link); 57 + }} 58 + /> 59 + ); 60 + } 61 62 + export default function ExtensionCard({ uniqueId, selectTag }: { uniqueId: number; selectTag: (tag: string) => void }) { 63 const { ext, enabled, busy, update, conflicting } = useStateFromStores([MoonbaseSettingsStore], () => { 64 return { 65 ext: MoonbaseSettingsStore.getExtension(uniqueId), ··· 70 }; 71 }); 72 73 + const [tab, setTab] = React.useState( 74 + update != null && ext?.changelog != null ? ExtensionPage.Changelog : ExtensionPage.Info 75 + ); 76 77 const tagline = ext.manifest?.meta?.tagline; 78 const settings = ext.settingsOverride ?? ext.manifest?.settings; 79 const description = ext.manifest?.meta?.description; 80 const changelog = ext.changelog; 81 + const linkButtons = [ 82 + ext?.manifest?.meta?.source && ( 83 + <PanelLinkButton icon={<AngleBracketsIcon />} tooltip="View source" link={ext.manifest.meta.source} /> 84 + ), 85 + ext?.source?.url && <PanelLinkButton icon={<ChannelListIcon />} tooltip="View repository" link={ext.source.url} />, 86 + ext?.manifest?.meta?.donate && ( 87 + <PanelLinkButton icon={<HeartIcon />} tooltip="Donate" link={ext.manifest.meta.donate} /> 88 + ) 89 + ].filter((x) => x != null); 90 + 91 const enabledDependants = useStateFromStores([MoonbaseSettingsStore], () => 92 Object.keys(MoonbaseSettingsStore.extensions) 93 .filter((uniqueId) => { 94 const potentialDependant = MoonbaseSettingsStore.getExtension(parseInt(uniqueId)); 95 96 return ( 97 + potentialDependant.manifest.dependencies?.includes(ext?.id) && 98 MoonbaseSettingsStore.getExtensionEnabled(parseInt(uniqueId)) 99 ); 100 }) ··· 102 ); 103 const implicitlyEnabled = enabledDependants.length > 0; 104 105 + const hasDuplicateEntry = useStateFromStores([MoonbaseSettingsStore], () => 106 + Object.entries(MoonbaseSettingsStore.extensions).some( 107 + ([otherUniqueId, otherExt]) => 108 + otherExt != null && otherExt?.id === ext?.id && parseInt(otherUniqueId) !== uniqueId 109 + ) 110 + ); 111 + 112 + return ext == null ? ( 113 + <></> 114 + ) : ( 115 + <Card editable={true} className={AppCardClasses.card}> 116 + <div className={AppCardClasses.cardHeader}> 117 <Flex direction={Flex.Direction.VERTICAL}> 118 <Flex direction={Flex.Direction.HORIZONTAL} align={Flex.Align.CENTER}> 119 <Text variant="text-md/semibold">{ext.manifest?.meta?.name ?? ext.id}</Text> 120 {ext.source.type === ExtensionLoadSource.Developer && ( 121 <Tooltip text="This is a local extension" position="top"> 122 + {(props: any) => <ScienceIcon {...props} class={BuildOverrideClasses.infoIcon} size="xs" />} 123 + </Tooltip> 124 + )} 125 + 126 + {hasDuplicateEntry && ext?.source?.url && ( 127 + <Tooltip text={`This extension is from the following repository: ${ext.source.url}`} position="top"> 128 + {(props: any) => <WindowTopOutlineIcon {...props} class={BuildOverrideClasses.infoIcon} size="xs" />} 129 + </Tooltip> 130 + )} 131 + 132 + {ext.manifest?.meta?.deprecated && ( 133 + <Tooltip text="This extension is deprecated" position="top"> 134 + {(props: any) => <WarningIcon {...props} class={BuildOverrideClasses.infoIcon} size="xs" />} 135 </Tooltip> 136 )} 137 </Flex> ··· 148 gap: "1rem" 149 }} 150 > 151 {ext.state === ExtensionState.NotDownloaded ? ( 152 <Tooltip 153 text={conflicting ? CONFLICTING_TEXT : COMPAT_TEXT_MAP[ext.compat]} ··· 203 disabled={implicitlyEnabled || ext.compat !== ExtensionCompat.Compatible} 204 hideBorder={true} 205 style={{ marginBottom: "0px" }} 206 + // @ts-expect-error fix type later 207 tooltipNote={ 208 + ext.compat !== ExtensionCompat.Compatible ? ( 209 + COMPAT_TEXT_MAP[ext.compat] 210 + ) : implicitlyEnabled ? ( 211 + <div style={{ display: "flex", flexDirection: "column" }}> 212 + <div>{`This extension is a dependency of the following enabled extension${ 213 + enabledDependants.length > 1 ? "s" : "" 214 + }:`}</div> 215 + {enabledDependants.map((dep) => ( 216 + <div>{"โ€ข " + (dep.manifest.meta?.name ?? dep.id)}</div> 217 + ))} 218 + </div> 219 + ) : undefined 220 } 221 onChange={() => { 222 const toggle = () => { ··· 249 </div> 250 251 <div> 252 + {(description != null || changelog != null || settings != null || linkButtons.length > 0) && ( 253 + <Flex> 254 + <TabBar 255 + selectedItem={tab} 256 + type="top" 257 + onItemSelect={setTab} 258 + className={DiscoveryClasses.tabBar} 259 + style={{ 260 + padding: "0 20px" 261 + }} 262 + > 263 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id={ExtensionPage.Info}> 264 + Info 265 </TabBar.Item> 266 + 267 + {description != null && ( 268 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id={ExtensionPage.Description}> 269 + Description 270 + </TabBar.Item> 271 + )} 272 + 273 + {changelog != null && ( 274 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id={ExtensionPage.Changelog}> 275 + Changelog 276 + </TabBar.Item> 277 + )} 278 279 + {settings != null && ( 280 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id={ExtensionPage.Settings}> 281 + Settings 282 + </TabBar.Item> 283 + )} 284 + </TabBar> 285 286 + <Flex 287 + align={Flex.Align.CENTER} 288 + justify={Flex.Justify.END} 289 + direction={Flex.Direction.HORIZONTAL} 290 + grow={1} 291 + className="moonbase-link-buttons" 292 + > 293 + {linkButtons.length > 0 && linkButtons} 294 + </Flex> 295 + </Flex> 296 )} 297 298 <Flex 299 justify={Flex.Justify.START} 300 wrap={Flex.Wrap.WRAP} 301 style={{ 302 + padding: "16px 16px", 303 + // This looks wonky in the settings tab 304 + rowGap: tab === ExtensionPage.Info ? "16px" : undefined 305 }} 306 > 307 + {tab === ExtensionPage.Info && <ExtensionInfo ext={ext} selectTag={selectTag} />} 308 {tab === ExtensionPage.Description && ( 309 <Text variant="text-md/normal" className={MarkupClasses.markup} style={{ width: "100%" }}> 310 {MarkupUtils.parse(description ?? "*No description*", true, { ··· 323 })} 324 </Text> 325 )} 326 + {tab === ExtensionPage.Settings && ( 327 + <ErrorBoundary> 328 + <Settings ext={ext} /> 329 + </ErrorBoundary> 330 + )} 331 </Flex> 332 </div> 333 </Card>
+67 -52
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/filterBar.tsx
··· 1 import { tagNames } from "./info"; 2 - 3 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 4 import * as React from "@moonlight-mod/wp/react"; 5 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; ··· 11 Popout, 12 Dialog, 13 Menu, 14 - MenuGroup, 15 - MenuCheckboxItem, 16 - MenuItem 17 } from "@moonlight-mod/wp/discord/components/common/index"; 18 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 19 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 20 21 export enum Filter { 22 Core = 1 << 0, ··· 26 Disabled = 1 << 4, 27 Installed = 1 << 5, 28 Repository = 1 << 6, 29 - Incompatible = 1 << 7 30 } 31 export const defaultFilter = 127 as Filter; 32 33 - const Margins = spacepack.findByCode("marginCenterHorz:")[0].exports; 34 - const SortMenuClasses = spacepack.findByCode("container:", "clearText:")[0].exports; 35 - 36 - let FilterDialogClasses: any; 37 - let FilterBarClasses: any; 38 spacepack 39 .lazyLoad('"Missing channel in Channel.openChannelContextMenu"', /e\("(\d+)"\)/g, /webpackId:(\d+?),/) 40 .then(() => { 41 - FilterBarClasses = spacepack.findByCode("tagsButtonWithCount:")[0].exports; 42 - FilterDialogClasses = spacepack.findByCode("countContainer:", "tagContainer:")[0].exports; 43 }); 44 45 - const TagItem = spacepack.findByCode('"forum-tag-"')[0].exports.Z; 46 - 47 - // FIXME: type component keys 48 - const { ChevronSmallDownIcon, ChevronSmallUpIcon, ArrowsUpDownIcon, RetryIcon, Tooltip } = Components; 49 - 50 function toggleTag(selectedTags: Set<string>, setSelectedTags: (tags: Set<string>) => void, tag: string) { 51 const newState = new Set(selectedTags); 52 if (newState.has(tag)) newState.delete(tag); ··· 123 checked={(filter & Filter.Incompatible) === Filter.Incompatible} 124 action={() => toggleFilter(Filter.Incompatible)} 125 /> 126 <MenuItem 127 id="reset-all" 128 className={SortMenuClasses.clearText} ··· 140 141 function TagButtonPopout({ selectedTags, setSelectedTags, setPopoutRef, closePopout }: any) { 142 return ( 143 - <Dialog ref={setPopoutRef} className={FilterDialogClasses.container}> 144 - <div className={FilterDialogClasses.header}> 145 - <div className={FilterDialogClasses.headerLeft}> 146 - <Heading color="interactive-normal" variant="text-xs/bold" className={FilterDialogClasses.headerText}> 147 Select tags 148 </Heading> 149 - <div className={FilterDialogClasses.countContainer}> 150 - <Text className={FilterDialogClasses.countText} color="none" variant="text-xs/medium"> 151 {selectedTags.size} 152 </Text> 153 </div> 154 </div> 155 </div> 156 - <div className={FilterDialogClasses.tagContainer}> 157 {Object.keys(tagNames).map((tag) => ( 158 <TagItem 159 key={tag} 160 - className={FilterDialogClasses.tag} 161 - tag={{ name: tagNames[tag as keyof typeof tagNames] }} 162 onClick={() => toggleTag(selectedTags, setSelectedTags, tag)} 163 selected={selectedTags.has(tag)} 164 /> 165 ))} 166 </div> 167 - <div className={FilterDialogClasses.separator} /> 168 <Button 169 look={Button.Looks.LINK} 170 size={Button.Sizes.MIN} 171 color={Button.Colors.CUSTOM} 172 - className={FilterDialogClasses.clear} 173 onClick={() => { 174 setSelectedTags(new Set()); 175 closePopout(); ··· 199 const tagsContainer = React.useRef<HTMLDivElement>(null); 200 const tagListInner = React.useRef<HTMLDivElement>(null); 201 const [tagsButtonOffset, setTagsButtonOffset] = React.useState(0); 202 React.useLayoutEffect(() => { 203 if (tagsContainer.current === null || tagListInner.current === null) return; 204 const { left: containerX, top: containerY } = tagsContainer.current.getBoundingClientRect(); ··· 220 style={{ 221 paddingTop: "12px" 222 }} 223 - className={`${FilterBarClasses.tagsContainer} ${Margins.marginBottom8}`} 224 > 225 <Tooltip text="Refresh updates" position="top"> 226 {(props: any) => ( ··· 228 {...props} 229 size={Button.Sizes.MIN} 230 color={Button.Colors.CUSTOM} 231 - className={`${FilterBarClasses.sortDropdown} moonbase-retry-button`} 232 - innerClassName={FilterBarClasses.sortDropdownInner} 233 - onClick={() => MoonbaseSettingsStore.checkUpdates()} 234 > 235 - <RetryIcon size={"custom"} width={16} /> 236 </Button> 237 )} 238 </Tooltip> ··· 248 {...props} 249 size={Button.Sizes.MIN} 250 color={Button.Colors.CUSTOM} 251 - className={FilterBarClasses.sortDropdown} 252 - innerClassName={FilterBarClasses.sortDropdownInner} 253 > 254 <ArrowsUpDownIcon size="xs" /> 255 - <Text className={FilterBarClasses.sortDropdownText} variant="text-sm/medium" color="interactive-normal"> 256 Sort & filter 257 </Text> 258 {isShown ? ( ··· 263 </Button> 264 )} 265 </Popout> 266 - <div className={FilterBarClasses.divider} /> 267 - <div className={FilterBarClasses.tagList}> 268 - <div ref={tagListInner} className={FilterBarClasses.tagListInner}> 269 {Object.keys(tagNames).map((tag) => ( 270 <TagItem 271 key={tag} 272 - className={FilterBarClasses.tag} 273 - tag={{ name: tagNames[tag as keyof typeof tagNames] }} 274 onClick={() => toggleTag(selectedTags, setSelectedTags, tag)} 275 selected={selectedTags.has(tag)} 276 /> ··· 298 left: tagsButtonOffset 299 }} 300 // TODO: Use Discord's class name utility 301 - className={`${FilterBarClasses.tagsButton} ${ 302 - selectedTags.size > 0 ? FilterBarClasses.tagsButtonWithCount : "" 303 - }`} 304 - innerClassName={FilterBarClasses.tagsButtonInner} 305 > 306 {selectedTags.size > 0 ? ( 307 - <div style={{ boxSizing: "content-box" }} className={FilterBarClasses.countContainer}> 308 - <Text className={FilterBarClasses.countText} color="none" variant="text-xs/medium"> 309 {selectedTags.size} 310 </Text> 311 </div> ··· 323 <Button 324 size={Button.Sizes.MIN} 325 color={Button.Colors.CUSTOM} 326 - className={`${FilterBarClasses.tagsButton} ${FilterBarClasses.tagsButtonPlaceholder}`} 327 - innerClassName={FilterBarClasses.tagsButtonInner} 328 > 329 {selectedTags.size > 0 ? ( 330 - <div style={{ boxSizing: "content-box" }} className={FilterBarClasses.countContainer}> 331 - <Text className={FilterBarClasses.countText} color="none" variant="text-xs/medium"> 332 {selectedTags.size} 333 </Text> 334 </div>
··· 1 import { tagNames } from "./info"; 2 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 3 import * as React from "@moonlight-mod/wp/react"; 4 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; ··· 10 Popout, 11 Dialog, 12 Menu, 13 + ChevronSmallDownIcon, 14 + ChevronSmallUpIcon, 15 + ArrowsUpDownIcon, 16 + RetryIcon, 17 + Tooltip 18 } from "@moonlight-mod/wp/discord/components/common/index"; 19 + import { MenuGroup, MenuCheckboxItem, MenuItem } from "@moonlight-mod/wp/contextMenu_contextMenu"; 20 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 21 + import Margins from "@moonlight-mod/wp/discord/styles/shared/Margins.css"; 22 + import TagItem from "@moonlight-mod/wp/discord/modules/forums/web/Tag"; 23 24 export enum Filter { 25 Core = 1 << 0, ··· 29 Disabled = 1 << 4, 30 Installed = 1 << 5, 31 Repository = 1 << 6, 32 + Incompatible = 1 << 7, 33 + Deprecated = 1 << 8 34 } 35 export const defaultFilter = 127 as Filter; 36 37 + let HeaderClasses: any; 38 + let ForumsClasses: any; 39 + let SortMenuClasses: any; 40 spacepack 41 .lazyLoad('"Missing channel in Channel.openChannelContextMenu"', /e\("(\d+)"\)/g, /webpackId:(\d+?),/) 42 .then(() => { 43 + ForumsClasses = spacepack.require("discord/modules/forums/web/Forums.css"); 44 + HeaderClasses = spacepack.require("discord/modules/forums/web/Header.css"); 45 + SortMenuClasses = spacepack.require("discord/modules/forums/web/SortMenu.css"); 46 }); 47 48 function toggleTag(selectedTags: Set<string>, setSelectedTags: (tags: Set<string>) => void, tag: string) { 49 const newState = new Set(selectedTags); 50 if (newState.has(tag)) newState.delete(tag); ··· 121 checked={(filter & Filter.Incompatible) === Filter.Incompatible} 122 action={() => toggleFilter(Filter.Incompatible)} 123 /> 124 + <MenuCheckboxItem 125 + id="l-deprecated" 126 + label="Show deprecated" 127 + checked={(filter & Filter.Deprecated) === Filter.Deprecated} 128 + action={() => toggleFilter(Filter.Deprecated)} 129 + /> 130 <MenuItem 131 id="reset-all" 132 className={SortMenuClasses.clearText} ··· 144 145 function TagButtonPopout({ selectedTags, setSelectedTags, setPopoutRef, closePopout }: any) { 146 return ( 147 + <Dialog ref={setPopoutRef} className={HeaderClasses.container}> 148 + <div className={HeaderClasses.header}> 149 + <div className={HeaderClasses.headerLeft}> 150 + <Heading color="interactive-normal" variant="text-xs/bold" className={HeaderClasses.headerText}> 151 Select tags 152 </Heading> 153 + <div className={HeaderClasses.countContainer}> 154 + <Text className={HeaderClasses.countText} color="none" variant="text-xs/medium"> 155 {selectedTags.size} 156 </Text> 157 </div> 158 </div> 159 </div> 160 + <div className={HeaderClasses.tagContainer}> 161 {Object.keys(tagNames).map((tag) => ( 162 <TagItem 163 key={tag} 164 + className={HeaderClasses.tag} 165 + tag={{ name: tagNames[tag as keyof typeof tagNames], id: tagNames[tag as keyof typeof tagNames] }} 166 onClick={() => toggleTag(selectedTags, setSelectedTags, tag)} 167 selected={selectedTags.has(tag)} 168 /> 169 ))} 170 </div> 171 + <div className={HeaderClasses.separator} /> 172 <Button 173 look={Button.Looks.LINK} 174 size={Button.Sizes.MIN} 175 color={Button.Colors.CUSTOM} 176 + className={HeaderClasses.clear} 177 onClick={() => { 178 setSelectedTags(new Set()); 179 closePopout(); ··· 203 const tagsContainer = React.useRef<HTMLDivElement>(null); 204 const tagListInner = React.useRef<HTMLDivElement>(null); 205 const [tagsButtonOffset, setTagsButtonOffset] = React.useState(0); 206 + const [checkingUpdates, setCheckingUpdates] = React.useState(false); 207 + 208 React.useLayoutEffect(() => { 209 if (tagsContainer.current === null || tagListInner.current === null) return; 210 const { left: containerX, top: containerY } = tagsContainer.current.getBoundingClientRect(); ··· 226 style={{ 227 paddingTop: "12px" 228 }} 229 + className={`${ForumsClasses.tagsContainer} ${Margins.marginBottom8}`} 230 > 231 <Tooltip text="Refresh updates" position="top"> 232 {(props: any) => ( ··· 234 {...props} 235 size={Button.Sizes.MIN} 236 color={Button.Colors.CUSTOM} 237 + className={`${ForumsClasses.sortDropdown} moonbase-retry-button`} 238 + innerClassName={ForumsClasses.sortDropdownInner} 239 + onClick={() => { 240 + (async () => { 241 + try { 242 + setCheckingUpdates(true); 243 + await MoonbaseSettingsStore.checkUpdates(); 244 + } finally { 245 + // artificial delay because the spin is fun 246 + await new Promise((r) => setTimeout(r, 500)); 247 + setCheckingUpdates(false); 248 + } 249 + })(); 250 + }} 251 > 252 + <RetryIcon size={"custom"} width={16} className={checkingUpdates ? "moonbase-speen" : ""} /> 253 </Button> 254 )} 255 </Tooltip> ··· 265 {...props} 266 size={Button.Sizes.MIN} 267 color={Button.Colors.CUSTOM} 268 + className={ForumsClasses.sortDropdown} 269 + innerClassName={ForumsClasses.sortDropdownInner} 270 > 271 <ArrowsUpDownIcon size="xs" /> 272 + <Text className={ForumsClasses.sortDropdownText} variant="text-sm/medium" color="interactive-normal"> 273 Sort & filter 274 </Text> 275 {isShown ? ( ··· 280 </Button> 281 )} 282 </Popout> 283 + <div className={ForumsClasses.divider} /> 284 + <div className={ForumsClasses.tagList}> 285 + <div ref={tagListInner} className={ForumsClasses.tagListInner}> 286 {Object.keys(tagNames).map((tag) => ( 287 <TagItem 288 key={tag} 289 + className={ForumsClasses.tag} 290 + tag={{ name: tagNames[tag as keyof typeof tagNames], id: tag }} 291 onClick={() => toggleTag(selectedTags, setSelectedTags, tag)} 292 selected={selectedTags.has(tag)} 293 /> ··· 315 left: tagsButtonOffset 316 }} 317 // TODO: Use Discord's class name utility 318 + className={`${ForumsClasses.tagsButton} ${selectedTags.size > 0 ? ForumsClasses.tagsButtonWithCount : ""}`} 319 + innerClassName={ForumsClasses.tagsButtonInner} 320 > 321 {selectedTags.size > 0 ? ( 322 + <div style={{ boxSizing: "content-box" }} className={ForumsClasses.countContainer}> 323 + <Text className={ForumsClasses.countText} color="none" variant="text-xs/medium"> 324 {selectedTags.size} 325 </Text> 326 </div> ··· 338 <Button 339 size={Button.Sizes.MIN} 340 color={Button.Colors.CUSTOM} 341 + className={`${ForumsClasses.tagsButton} ${ForumsClasses.tagsButtonPlaceholder}`} 342 + innerClassName={ForumsClasses.tagsButtonInner} 343 > 344 {selectedTags.size > 0 ? ( 345 + <div style={{ boxSizing: "content-box" }} className={ForumsClasses.countContainer}> 346 + <Text className={ForumsClasses.countText} color="none" variant="text-xs/medium"> 347 {selectedTags.size} 348 </Text> 349 </div>
+49 -15
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/index.tsx
··· 6 import React from "@moonlight-mod/wp/react"; 7 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 8 import { useStateFromStoresObject } from "@moonlight-mod/wp/discord/packages/flux"; 9 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 10 11 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 12 import { ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 13 import HelpMessage from "../HelpMessage"; 14 15 - const SearchBar: any = Object.values(spacepack.findByCode("hideSearchIcon")[0].exports)[0]; 16 - const { FormDivider, CircleInformationIcon, XSmallIcon } = Components; 17 - const PanelButton = spacepack.findByCode("Masks.PANEL_BUTTON")[0].exports.Z; 18 19 export default function ExtensionsPage() { 20 - const { extensions, savedFilter, showOnlyUpdateable } = useStateFromStoresObject([MoonbaseSettingsStore], () => { 21 return { 22 extensions: MoonbaseSettingsStore.extensions, 23 - savedFilter: MoonbaseSettingsStore.getExtensionConfigRaw<number>("moonbase", "filter", defaultFilter), 24 - showOnlyUpdateable: MoonbaseSettingsStore.showOnlyUpdateable 25 }; 26 }); 27 28 const [query, setQuery] = React.useState(""); 29 30 const filterState = React.useState(defaultFilter); 31 ··· 37 filter = filterState[0]; 38 setFilter = filterState[1]; 39 } 40 const [selectedTags, setSelectedTags] = React.useState(new Set<string>()); 41 const sorted = Object.values(extensions).sort((a, b) => { 42 const aName = a.manifest.meta?.name ?? a.id; 43 const bName = b.manifest.meta?.name ?? b.id; ··· 72 ) && 73 (filter & Filter.Incompatible || 74 ext.compat === ExtensionCompat.Compatible || 75 - (ext.compat === ExtensionCompat.InvalidApiLevel && ext.hasUpdate)) 76 ); 77 78 // Prioritize extensions with updates 79 const filteredWithUpdates = filtered.filter((ext) => ext!.hasUpdate); 80 - const filterUpdates = showOnlyUpdateable && filteredWithUpdates.length > 0; 81 - const filteredWithoutUpdates = filterUpdates ? [] : filtered.filter((ext) => !ext!.hasUpdate); 82 83 return ( 84 <> ··· 97 /> 98 <FilterBar filter={filter} setFilter={setFilter} selectedTags={selectedTags} setSelectedTags={setSelectedTags} /> 99 100 - {filterUpdates && ( 101 <HelpMessage 102 icon={CircleInformationIcon} 103 - text="Only displaying updates" 104 className="moonbase-extension-update-section" 105 > 106 <div className="moonbase-help-message-buttons"> 107 <PanelButton 108 icon={XSmallIcon} 109 onClick={() => { 110 - MoonbaseSettingsStore.showOnlyUpdateable = false; 111 }} 112 /> 113 </div> ··· 115 )} 116 117 {filteredWithUpdates.map((ext) => ( 118 - <ExtensionCard uniqueId={ext.uniqueId} key={ext.uniqueId} /> 119 ))} 120 {filteredWithUpdates.length > 0 && filteredWithoutUpdates.length > 0 && ( 121 <FormDivider className="moonbase-update-divider" /> 122 )} 123 {filteredWithoutUpdates.map((ext) => ( 124 - <ExtensionCard uniqueId={ext.uniqueId} key={ext.uniqueId} /> 125 ))} 126 </> 127 );
··· 6 import React from "@moonlight-mod/wp/react"; 7 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 8 import { useStateFromStoresObject } from "@moonlight-mod/wp/discord/packages/flux"; 9 + import { 10 + FormDivider, 11 + CircleInformationIcon, 12 + XSmallIcon, 13 + Button 14 + } from "@moonlight-mod/wp/discord/components/common/index"; 15 + import PanelButton from "@moonlight-mod/wp/discord/components/common/PanelButton"; 16 17 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 18 + import ErrorBoundary from "@moonlight-mod/wp/common_ErrorBoundary"; 19 import { ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 20 import HelpMessage from "../HelpMessage"; 21 22 + const SearchBar = spacepack.require("discord/uikit/search/SearchBar").default; 23 + 24 + const validTags: string[] = Object.values(ExtensionTag); 25 26 export default function ExtensionsPage() { 27 + const { extensions, savedFilter } = useStateFromStoresObject([MoonbaseSettingsStore], () => { 28 return { 29 extensions: MoonbaseSettingsStore.extensions, 30 + savedFilter: MoonbaseSettingsStore.getExtensionConfigRaw<number>("moonbase", "filter", defaultFilter) 31 }; 32 }); 33 34 const [query, setQuery] = React.useState(""); 35 + const [hitUpdateAll, setHitUpdateAll] = React.useState(false); 36 37 const filterState = React.useState(defaultFilter); 38 ··· 44 filter = filterState[0]; 45 setFilter = filterState[1]; 46 } 47 + 48 const [selectedTags, setSelectedTags] = React.useState(new Set<string>()); 49 + const selectTag = React.useCallback( 50 + (tag: string) => { 51 + const newState = new Set(selectedTags); 52 + if (validTags.includes(tag)) newState.add(tag); 53 + setSelectedTags(newState); 54 + }, 55 + [selectedTags] 56 + ); 57 + 58 const sorted = Object.values(extensions).sort((a, b) => { 59 const aName = a.manifest.meta?.name ?? a.id; 60 const bName = b.manifest.meta?.name ?? b.id; ··· 89 ) && 90 (filter & Filter.Incompatible || 91 ext.compat === ExtensionCompat.Compatible || 92 + (ext.compat === ExtensionCompat.InvalidApiLevel && ext.hasUpdate)) && 93 + (filter & Filter.Deprecated || 94 + ext.manifest?.meta?.deprecated !== true || 95 + ext.state !== ExtensionState.NotDownloaded) 96 ); 97 98 // Prioritize extensions with updates 99 const filteredWithUpdates = filtered.filter((ext) => ext!.hasUpdate); 100 + const filteredWithoutUpdates = filtered.filter((ext) => !ext!.hasUpdate); 101 102 return ( 103 <> ··· 116 /> 117 <FilterBar filter={filter} setFilter={setFilter} selectedTags={selectedTags} setSelectedTags={setSelectedTags} /> 118 119 + {filteredWithUpdates.length > 0 && ( 120 <HelpMessage 121 icon={CircleInformationIcon} 122 + text="Extension updates are available" 123 className="moonbase-extension-update-section" 124 > 125 <div className="moonbase-help-message-buttons"> 126 + <Button 127 + color={Button.Colors.BRAND} 128 + size={Button.Sizes.TINY} 129 + disabled={hitUpdateAll} 130 + onClick={() => { 131 + setHitUpdateAll(true); 132 + MoonbaseSettingsStore.updateAllExtensions(); 133 + }} 134 + > 135 + Update all 136 + </Button> 137 <PanelButton 138 icon={XSmallIcon} 139 onClick={() => { 140 + MoonbaseSettingsStore.dismissAllExtensionUpdates(); 141 }} 142 /> 143 </div> ··· 145 )} 146 147 {filteredWithUpdates.map((ext) => ( 148 + <ErrorBoundary> 149 + <ExtensionCard uniqueId={ext.uniqueId} key={ext.uniqueId} selectTag={selectTag} /> 150 + </ErrorBoundary> 151 ))} 152 {filteredWithUpdates.length > 0 && filteredWithoutUpdates.length > 0 && ( 153 <FormDivider className="moonbase-update-divider" /> 154 )} 155 {filteredWithoutUpdates.map((ext) => ( 156 + <ErrorBoundary> 157 + <ExtensionCard uniqueId={ext.uniqueId} key={ext.uniqueId} selectTag={selectTag} /> 158 + </ErrorBoundary> 159 ))} 160 </> 161 );
+55 -26
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/info.tsx
··· 2 import { MoonbaseExtension } from "../../../types"; 3 4 import React from "@moonlight-mod/wp/react"; 5 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 6 - import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 7 8 type Dependency = { 9 id: string; ··· 34 [ExtensionTag.Library]: "Library" 35 }; 36 37 - const UserInfoClasses = spacepack.findByCode("infoScroller", "userInfoSection", "userInfoSectionHeader")[0].exports; 38 - 39 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 40 - 41 - // FIXME: type component keys 42 - const { Text } = Components; 43 44 function InfoSection({ title, children }: { title: string; children: React.ReactNode }) { 45 return ( ··· 48 marginRight: "1em" 49 }} 50 > 51 - <Text variant="eyebrow" className={UserInfoClasses.userInfoSectionHeader}> 52 {title} 53 </Text> 54 ··· 57 ); 58 } 59 60 - function Badge({ color, children }: { color: string; children: React.ReactNode }) { 61 return ( 62 <span 63 - style={{ 64 - borderRadius: ".1875rem", 65 - padding: "0 0.275rem", 66 - marginRight: "0.4em", 67 - backgroundColor: color, 68 - color: "#fff" 69 - }} 70 > 71 {children} 72 </span> 73 ); 74 } 75 76 - export default function ExtensionInfo({ ext }: { ext: MoonbaseExtension }) { 77 const authors = ext.manifest?.meta?.authors; 78 const tags = ext.manifest?.meta?.tags; 79 const version = ext.manifest?.version; 80 81 const dependencies: Dependency[] = []; 82 if (ext.manifest.dependencies != null) { 83 dependencies.push( 84 ...ext.manifest.dependencies.map((dep) => ({ ··· 98 } 99 100 if (ext.manifest.incompatible != null) { 101 - dependencies.push( 102 ...ext.manifest.incompatible.map((dep) => ({ 103 id: dep, 104 type: DependencyType.Incompatible ··· 136 <InfoSection title="Tags"> 137 {tags.map((tag, i) => { 138 const name = tagNames[tag]; 139 140 return ( 141 - <Badge key={i} color={tag === ExtensionTag.DangerZone ? "var(--red-400)" : "var(--brand-500)"}> 142 {name} 143 </Badge> 144 ); ··· 149 {dependencies.length > 0 && ( 150 <InfoSection title="Dependencies"> 151 {dependencies.map((dep) => { 152 - const colors = { 153 - [DependencyType.Dependency]: "var(--brand-500)", 154 - [DependencyType.Optional]: "var(--orange-400)", 155 - [DependencyType.Incompatible]: "var(--red-400)" 156 - }; 157 - const color = colors[dep.type]; 158 const name = MoonbaseSettingsStore.tryGetExtensionName(dep.id); 159 160 return ( 161 - <Badge color={color} key={dep.id}> 162 {name} 163 </Badge> 164 );
··· 2 import { MoonbaseExtension } from "../../../types"; 3 4 import React from "@moonlight-mod/wp/react"; 5 + import { Text } from "@moonlight-mod/wp/discord/components/common/index"; 6 7 type Dependency = { 8 id: string; ··· 33 [ExtensionTag.Library]: "Library" 34 }; 35 36 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 37 38 function InfoSection({ title, children }: { title: string; children: React.ReactNode }) { 39 return ( ··· 42 marginRight: "1em" 43 }} 44 > 45 + <Text variant="eyebrow" className="moonlight-card-info-header"> 46 {title} 47 </Text> 48 ··· 51 ); 52 } 53 54 + function Badge({ 55 + color, 56 + children, 57 + style = {}, 58 + onClick 59 + }: { 60 + color: string; 61 + children: React.ReactNode; 62 + style?: React.CSSProperties; 63 + onClick?: () => void; 64 + }) { 65 + if (onClick) style.cursor ??= "pointer"; 66 return ( 67 <span 68 + className="moonlight-card-badge" 69 + style={ 70 + { 71 + "--badge-color": color, 72 + ...style 73 + } as React.CSSProperties 74 + } 75 + onClick={onClick} 76 > 77 {children} 78 </span> 79 ); 80 } 81 82 + export default function ExtensionInfo({ 83 + ext, 84 + selectTag 85 + }: { 86 + ext: MoonbaseExtension; 87 + selectTag: (tag: string) => void; 88 + }) { 89 const authors = ext.manifest?.meta?.authors; 90 const tags = ext.manifest?.meta?.tags; 91 const version = ext.manifest?.version; 92 93 const dependencies: Dependency[] = []; 94 + const incompatible: Dependency[] = []; 95 + 96 if (ext.manifest.dependencies != null) { 97 dependencies.push( 98 ...ext.manifest.dependencies.map((dep) => ({ ··· 112 } 113 114 if (ext.manifest.incompatible != null) { 115 + incompatible.push( 116 ...ext.manifest.incompatible.map((dep) => ({ 117 id: dep, 118 type: DependencyType.Incompatible ··· 150 <InfoSection title="Tags"> 151 {tags.map((tag, i) => { 152 const name = tagNames[tag]; 153 + let color = "var(--bg-mod-strong)"; 154 + let style; 155 + if (tag === ExtensionTag.DangerZone) { 156 + color = "var(--red-460)"; 157 + style = { color: "var(--primary-230)" }; 158 + } 159 160 return ( 161 + <Badge key={i} color={color} style={style} onClick={() => selectTag(tag)}> 162 {name} 163 </Badge> 164 ); ··· 169 {dependencies.length > 0 && ( 170 <InfoSection title="Dependencies"> 171 {dependencies.map((dep) => { 172 const name = MoonbaseSettingsStore.tryGetExtensionName(dep.id); 173 174 + // TODO: figure out a decent way to distinguish suggested 175 return ( 176 + <Badge color="var(--bg-mod-strong)" key={dep.id}> 177 + {name} 178 + </Badge> 179 + ); 180 + })} 181 + </InfoSection> 182 + )} 183 + 184 + {incompatible.length > 0 && ( 185 + <InfoSection title="Incompatible"> 186 + {incompatible.map((dep) => { 187 + const name = MoonbaseSettingsStore.tryGetExtensionName(dep.id); 188 + 189 + return ( 190 + <Badge color="var(--bg-mod-strong)" key={dep.id}> 191 {name} 192 </Badge> 193 );
+15 -11
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/popup.tsx
··· 1 // TODO: clean up the styling here 2 - import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 3 import React from "@moonlight-mod/wp/react"; 4 import { MoonbaseExtension } from "core-extensions/src/moonbase/types"; 5 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 6 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 7 import { ExtensionLoadSource } from "@moonlight-mod/types"; 8 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 9 10 - const { openModalLazy, useModalsStore, closeModal } = Components; 11 - const Popup = spacepack.findByCode(".minorContainer", "secondaryAction")[0].exports.default; 12 13 function close() { 14 const ModalStore = useModalsStore.getState(); 15 closeModal(ModalStore.default[0].key); 16 } 17 18 const presentableLoadSources: Record<ExtensionLoadSource, string> = { 19 [ExtensionLoadSource.Developer]: "Local extension", // should never show up 20 [ExtensionLoadSource.Core]: "Core extension", ··· 32 option: string | undefined; 33 setOption: (pick: string | undefined) => void; 34 }) { 35 - const { SingleSelect } = Components; 36 - 37 return ( 38 <SingleSelect 39 key={id} ··· 61 deps: Record<string, MoonbaseExtension[]>; 62 transitionState: number | null; 63 }) { 64 - const { Text } = Components; 65 - 66 const amountNotAvailable = Object.values(deps).filter((candidates) => candidates.length === 0).length; 67 68 const [options, setOptions] = React.useState<Record<string, string | undefined>>( ··· 75 ); 76 77 return ( 78 - <Popup 79 body={ 80 <Flex 81 style={{ ··· 168 uniqueId: number; 169 cb: () => void; 170 }) { 171 - const { Text } = Components; 172 173 return ( 174 - <Popup 175 title={title} 176 body={ 177 <Flex>
··· 1 // TODO: clean up the styling here 2 import React from "@moonlight-mod/wp/react"; 3 import { MoonbaseExtension } from "core-extensions/src/moonbase/types"; 4 + import { openModalLazy, useModalsStore, closeModal } from "@moonlight-mod/wp/discord/modules/modals/Modals"; 5 + import { SingleSelect, Text } from "@moonlight-mod/wp/discord/components/common/index"; 6 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 7 import { ExtensionLoadSource } from "@moonlight-mod/types"; 8 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 9 + import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 10 11 + let ConfirmModal: typeof import("@moonlight-mod/wp/discord/components/modals/ConfirmModal").default; 12 13 function close() { 14 const ModalStore = useModalsStore.getState(); 15 closeModal(ModalStore.default[0].key); 16 } 17 18 + // do this to avoid a hard dependency 19 + function lazyLoad() { 20 + if (!ConfirmModal) { 21 + ConfirmModal = spacepack.require("discord/components/modals/ConfirmModal").default; 22 + } 23 + } 24 + 25 const presentableLoadSources: Record<ExtensionLoadSource, string> = { 26 [ExtensionLoadSource.Developer]: "Local extension", // should never show up 27 [ExtensionLoadSource.Core]: "Core extension", ··· 39 option: string | undefined; 40 setOption: (pick: string | undefined) => void; 41 }) { 42 return ( 43 <SingleSelect 44 key={id} ··· 66 deps: Record<string, MoonbaseExtension[]>; 67 transitionState: number | null; 68 }) { 69 + lazyLoad(); 70 const amountNotAvailable = Object.values(deps).filter((candidates) => candidates.length === 0).length; 71 72 const [options, setOptions] = React.useState<Record<string, string | undefined>>( ··· 79 ); 80 81 return ( 82 + <ConfirmModal 83 body={ 84 <Flex 85 style={{ ··· 172 uniqueId: number; 173 cb: () => void; 174 }) { 175 + lazyLoad(); 176 177 return ( 178 + <ConfirmModal 179 title={title} 180 body={ 181 <Flex>
+84 -50
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/settings.tsx
··· 11 12 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 13 import React from "@moonlight-mod/wp/react"; 14 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 15 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 16 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 17 18 type SettingsProps = { 19 ext: MoonbaseExtension; ··· 21 setting: ExtensionSettingsManifest; 22 disabled: boolean; 23 }; 24 - 25 type SettingsComponent = React.ComponentType<SettingsProps>; 26 27 - import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 28 const Margins = spacepack.require("discord/styles/shared/Margins.css"); 29 30 function useConfigEntry<T>(uniqueId: number, name: string) { 31 return useStateFromStores( 32 [MoonbaseSettingsStore], ··· 42 } 43 44 function Boolean({ ext, name, setting, disabled }: SettingsProps) { 45 - const { FormSwitch } = Components; 46 const { value, displayName, description } = useConfigEntry<boolean>(ext.uniqueId, name); 47 48 return ( ··· 53 onChange={(value: boolean) => { 54 MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value); 55 }} 56 - note={description} 57 className={`${Margins.marginReset} ${Margins.marginTop20}`} 58 > 59 {displayName} ··· 62 } 63 64 function Number({ ext, name, setting, disabled }: SettingsProps) { 65 - const { FormItem, FormText, Slider } = Components; 66 const { value, displayName, description } = useConfigEntry<number>(ext.uniqueId, name); 67 68 const castedSetting = setting as NumberSettingType; 69 - const min = castedSetting.min ?? 0; 70 - const max = castedSetting.max ?? 100; 71 72 return ( 73 <FormItem className={Margins.marginTop20} title={displayName}> 74 - {description && <FormText>{description}</FormText>} 75 - <Slider 76 - initialValue={value ?? 0} 77 - disabled={disabled} 78 - minValue={castedSetting.min ?? 0} 79 - maxValue={castedSetting.max ?? 100} 80 - onValueChange={(value: number) => { 81 - const rounded = Math.max(min, Math.min(max, Math.round(value))); 82 - MoonbaseSettingsStore.setExtensionConfig(ext.id, name, rounded); 83 - }} 84 - /> 85 </FormItem> 86 ); 87 } 88 89 function String({ ext, name, setting, disabled }: SettingsProps) { 90 - const { FormItem, FormText, TextInput } = Components; 91 const { value, displayName, description } = useConfigEntry<string>(ext.uniqueId, name); 92 93 return ( 94 <FormItem className={Margins.marginTop20} title={displayName}> 95 - {description && <FormText className={Margins.marginBottom8}>{description}</FormText>} 96 <TextInput 97 value={value ?? ""} 98 - onChange={(value: string) => { 99 - if (disabled) return; 100 - MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value); 101 - }} 102 /> 103 </FormItem> 104 ); 105 } 106 107 function MultilineString({ ext, name, setting, disabled }: SettingsProps) { 108 - const { FormItem, FormText, TextArea } = Components; 109 const { value, displayName, description } = useConfigEntry<string>(ext.uniqueId, name); 110 111 return ( 112 <FormItem className={Margins.marginTop20} title={displayName}> 113 - {description && <FormText className={Margins.marginBottom8}>{description}</FormText>} 114 <TextArea 115 rows={5} 116 value={value ?? ""} 117 className={"moonbase-resizeable"} 118 - onChange={(value: string) => { 119 - if (disabled) return; 120 - MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value); 121 - }} 122 /> 123 </FormItem> 124 ); 125 } 126 127 function Select({ ext, name, setting, disabled }: SettingsProps) { 128 - const { FormItem, FormText, SingleSelect } = Components; 129 const { value, displayName, description } = useConfigEntry<string>(ext.uniqueId, name); 130 131 const castedSetting = setting as SelectSettingType; ··· 133 134 return ( 135 <FormItem className={Margins.marginTop20} title={displayName}> 136 - {description && <FormText className={Margins.marginBottom8}>{description}</FormText>} 137 <SingleSelect 138 autofocus={false} 139 clearable={false} ··· 149 } 150 151 function MultiSelect({ ext, name, setting, disabled }: SettingsProps) { 152 - const { FormItem, FormText, Select, useVariableSelect, multiSelect } = Components; 153 const { value, displayName, description } = useConfigEntry<string | string[]>(ext.uniqueId, name); 154 155 const castedSetting = setting as MultiSelectSettingType; ··· 157 158 return ( 159 <FormItem className={Margins.marginTop20} title={displayName}> 160 - {description && <FormText className={Margins.marginBottom8}>{description}</FormText>} 161 - <Select 162 autofocus={false} 163 clearable={false} 164 closeOnSelect={false} ··· 175 </FormItem> 176 ); 177 } 178 - 179 - const RemoveButtonClasses = spacepack.findByCode("removeButtonContainer")[0].exports; 180 - 181 - // FIXME: type component keys 182 - const { CircleXIcon } = Components; 183 184 function RemoveEntryButton({ onClick, disabled }: { onClick: () => void; disabled: boolean }) { 185 - const { Tooltip, Clickable } = Components; 186 return ( 187 - <div className={RemoveButtonClasses.removeButtonContainer}> 188 <Tooltip text="Remove entry" position="top"> 189 {(props: any) => ( 190 - <Clickable {...props} className={RemoveButtonClasses.removeButton} onClick={onClick}> 191 <CircleXIcon width={16} height={16} /> 192 </Clickable> 193 )} ··· 197 } 198 199 function List({ ext, name, setting, disabled }: SettingsProps) { 200 - const { FormItem, FormText, TextInput, Button } = Components; 201 const { value, displayName, description } = useConfigEntry<string[]>(ext.uniqueId, name); 202 203 const entries = value ?? []; ··· 205 206 return ( 207 <FormItem className={Margins.marginTop20} title={displayName}> 208 - {description && <FormText className={Margins.marginBottom4}>{description}</FormText>} 209 <Flex direction={Flex.Direction.VERTICAL}> 210 {entries.map((val, i) => ( 211 // FIXME: stylesheets ··· 257 } 258 259 function Dictionary({ ext, name, setting, disabled }: SettingsProps) { 260 - const { FormItem, FormText, TextInput, Button } = Components; 261 const { value, displayName, description } = useConfigEntry<Record<string, string>>(ext.uniqueId, name); 262 263 const entries = Object.entries(value ?? {}); ··· 265 266 return ( 267 <FormItem className={Margins.marginTop20} title={displayName}> 268 - {description && <FormText className={Margins.marginBottom4}>{description}</FormText>} 269 <Flex direction={Flex.Direction.VERTICAL}> 270 {entries.map(([key, val], i) => ( 271 // FIXME: stylesheets ··· 339 ); 340 341 if (Component == null) { 342 - const { Text } = Components; 343 return ( 344 <Text variant="text-md/normal">{`Custom setting "${displayName}" is missing a component. Perhaps the extension is not installed?`}</Text> 345 ); 346 } 347 348 return ( 349 - <Component value={value} setValue={(value) => MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value)} /> 350 ); 351 } 352
··· 11 12 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 13 import React from "@moonlight-mod/wp/react"; 14 + import { 15 + FormSwitch, 16 + FormItem, 17 + FormText, 18 + TextInput, 19 + Slider, 20 + TextArea, 21 + Tooltip, 22 + Clickable, 23 + CircleXIcon, 24 + Text, 25 + SingleSelect, 26 + Button, 27 + useVariableSelect, 28 + multiSelect, 29 + Select as DiscordSelect, 30 + NumberInputStepper 31 + } from "@moonlight-mod/wp/discord/components/common/index"; 32 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 33 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 34 + import MarkupUtils from "@moonlight-mod/wp/discord/modules/markup/MarkupUtils"; 35 + import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 36 + import ErrorBoundary from "@moonlight-mod/wp/common_ErrorBoundary"; 37 + 38 + let GuildSettingsRoleEditClasses: any; 39 + spacepack 40 + .lazyLoad( 41 + "renderArtisanalHack", 42 + /\[(?:.\.e\("\d+?"\),?)+\][^}]+?webpackId:\d+,name:"GuildSettings"/, 43 + /webpackId:(\d+),name:"GuildSettings"/ 44 + ) 45 + .then( 46 + () => 47 + (GuildSettingsRoleEditClasses = spacepack.require( 48 + "discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css" 49 + )) 50 + ); 51 52 type SettingsProps = { 53 ext: MoonbaseExtension; ··· 55 setting: ExtensionSettingsManifest; 56 disabled: boolean; 57 }; 58 type SettingsComponent = React.ComponentType<SettingsProps>; 59 60 const Margins = spacepack.require("discord/styles/shared/Margins.css"); 61 62 + function markdownify(str: string) { 63 + return MarkupUtils.parse(str, true, { 64 + hideSimpleEmbedContent: true, 65 + allowLinks: true 66 + }); 67 + } 68 + 69 function useConfigEntry<T>(uniqueId: number, name: string) { 70 return useStateFromStores( 71 [MoonbaseSettingsStore], ··· 81 } 82 83 function Boolean({ ext, name, setting, disabled }: SettingsProps) { 84 const { value, displayName, description } = useConfigEntry<boolean>(ext.uniqueId, name); 85 86 return ( ··· 91 onChange={(value: boolean) => { 92 MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value); 93 }} 94 + note={description != null ? markdownify(description) : undefined} 95 className={`${Margins.marginReset} ${Margins.marginTop20}`} 96 > 97 {displayName} ··· 100 } 101 102 function Number({ ext, name, setting, disabled }: SettingsProps) { 103 const { value, displayName, description } = useConfigEntry<number>(ext.uniqueId, name); 104 105 const castedSetting = setting as NumberSettingType; 106 + const min = castedSetting.min; 107 + const max = castedSetting.max; 108 + 109 + const onChange = (value: number) => { 110 + const rounded = min == null || max == null ? Math.round(value) : Math.max(min, Math.min(max, Math.round(value))); 111 + MoonbaseSettingsStore.setExtensionConfig(ext.id, name, rounded); 112 + }; 113 114 return ( 115 <FormItem className={Margins.marginTop20} title={displayName}> 116 + {min == null || max == null ? ( 117 + <Flex justify={Flex.Justify.BETWEEN} direction={Flex.Direction.HORIZONTAL}> 118 + {description && <FormText>{markdownify(description)}</FormText>} 119 + <NumberInputStepper value={value ?? 0} onChange={onChange} /> 120 + </Flex> 121 + ) : ( 122 + <> 123 + {description && <FormText>{markdownify(description)}</FormText>} 124 + <Slider 125 + initialValue={value ?? 0} 126 + disabled={disabled} 127 + minValue={min} 128 + maxValue={max} 129 + onValueChange={onChange} 130 + onValueRender={(value: number) => `${Math.round(value)}`} 131 + /> 132 + </> 133 + )} 134 </FormItem> 135 ); 136 } 137 138 function String({ ext, name, setting, disabled }: SettingsProps) { 139 const { value, displayName, description } = useConfigEntry<string>(ext.uniqueId, name); 140 141 return ( 142 <FormItem className={Margins.marginTop20} title={displayName}> 143 + {description && <FormText className={Margins.marginBottom8}>{markdownify(description)}</FormText>} 144 <TextInput 145 value={value ?? ""} 146 + disabled={disabled} 147 + onChange={(value: string) => MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value)} 148 /> 149 </FormItem> 150 ); 151 } 152 153 function MultilineString({ ext, name, setting, disabled }: SettingsProps) { 154 const { value, displayName, description } = useConfigEntry<string>(ext.uniqueId, name); 155 156 return ( 157 <FormItem className={Margins.marginTop20} title={displayName}> 158 + {description && <FormText className={Margins.marginBottom8}>{markdownify(description)}</FormText>} 159 <TextArea 160 rows={5} 161 value={value ?? ""} 162 + disabled={disabled} 163 className={"moonbase-resizeable"} 164 + onChange={(value: string) => MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value)} 165 /> 166 </FormItem> 167 ); 168 } 169 170 function Select({ ext, name, setting, disabled }: SettingsProps) { 171 const { value, displayName, description } = useConfigEntry<string>(ext.uniqueId, name); 172 173 const castedSetting = setting as SelectSettingType; ··· 175 176 return ( 177 <FormItem className={Margins.marginTop20} title={displayName}> 178 + {description && <FormText className={Margins.marginBottom8}>{markdownify(description)}</FormText>} 179 <SingleSelect 180 autofocus={false} 181 clearable={false} ··· 191 } 192 193 function MultiSelect({ ext, name, setting, disabled }: SettingsProps) { 194 const { value, displayName, description } = useConfigEntry<string | string[]>(ext.uniqueId, name); 195 196 const castedSetting = setting as MultiSelectSettingType; ··· 198 199 return ( 200 <FormItem className={Margins.marginTop20} title={displayName}> 201 + {description && <FormText className={Margins.marginBottom8}>{markdownify(description)}</FormText>} 202 + <DiscordSelect 203 autofocus={false} 204 clearable={false} 205 closeOnSelect={false} ··· 216 </FormItem> 217 ); 218 } 219 220 function RemoveEntryButton({ onClick, disabled }: { onClick: () => void; disabled: boolean }) { 221 return ( 222 + <div className={GuildSettingsRoleEditClasses.removeButtonContainer}> 223 <Tooltip text="Remove entry" position="top"> 224 {(props: any) => ( 225 + <Clickable {...props} className={GuildSettingsRoleEditClasses.removeButton} onClick={onClick}> 226 <CircleXIcon width={16} height={16} /> 227 </Clickable> 228 )} ··· 232 } 233 234 function List({ ext, name, setting, disabled }: SettingsProps) { 235 const { value, displayName, description } = useConfigEntry<string[]>(ext.uniqueId, name); 236 237 const entries = value ?? []; ··· 239 240 return ( 241 <FormItem className={Margins.marginTop20} title={displayName}> 242 + {description && <FormText className={Margins.marginBottom4}>{markdownify(description)}</FormText>} 243 <Flex direction={Flex.Direction.VERTICAL}> 244 {entries.map((val, i) => ( 245 // FIXME: stylesheets ··· 291 } 292 293 function Dictionary({ ext, name, setting, disabled }: SettingsProps) { 294 const { value, displayName, description } = useConfigEntry<Record<string, string>>(ext.uniqueId, name); 295 296 const entries = Object.entries(value ?? {}); ··· 298 299 return ( 300 <FormItem className={Margins.marginTop20} title={displayName}> 301 + {description && <FormText className={Margins.marginBottom4}>{markdownify(description)}</FormText>} 302 <Flex direction={Flex.Direction.VERTICAL}> 303 {entries.map(([key, val], i) => ( 304 // FIXME: stylesheets ··· 372 ); 373 374 if (Component == null) { 375 return ( 376 <Text variant="text-md/normal">{`Custom setting "${displayName}" is missing a component. Perhaps the extension is not installed?`}</Text> 377 ); 378 } 379 380 return ( 381 + <ErrorBoundary> 382 + <Component value={value} setValue={(value) => MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value)} /> 383 + </ErrorBoundary> 384 ); 385 } 386
+22 -15
packages/core-extensions/src/moonbase/webpackModules/ui/index.tsx
··· 1 import React from "@moonlight-mod/wp/react"; 2 - import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 3 import { Text, TabBar } from "@moonlight-mod/wp/discord/components/common/index"; 4 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 5 import { UserSettingsModalStore } from "@moonlight-mod/wp/common_stores"; 6 7 import ExtensionsPage from "./extensions"; 8 import ConfigPage from "./config"; 9 import Update from "./update"; 10 - import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 11 import RestartAdviceMessage from "./RestartAdvice"; 12 - 13 - const { Divider } = spacepack.findByCode(".forumOrHome]:")[0].exports.Z; 14 - const TitleBarClasses = spacepack.findByCode("iconWrapper:", "children:")[0].exports; 15 - const TabBarClasses = spacepack.findByCode("nowPlayingColumn:")[0].exports; 16 - const { setSection, clearSubsection } = spacepack.findByCode(':"USER_SETTINGS_MODAL_SET_SECTION"')[0].exports.Z; 17 - const Margins = spacepack.require("discord/styles/shared/Margins.css"); 18 19 export const pages: { 20 id: string; ··· 30 id: "config", 31 name: "Config", 32 element: ConfigPage 33 } 34 ]; 35 ··· 37 const subsection = useStateFromStores([UserSettingsModalStore], () => UserSettingsModalStore.getSubsection() ?? 0); 38 const setSubsection = React.useCallback( 39 (to: string) => { 40 - if (subsection !== to) setSection("moonbase", to); 41 }, 42 [subsection] 43 ); ··· 45 React.useEffect( 46 () => () => { 47 // Normally there's an onSettingsClose prop you can set but we don't expose it and I don't care enough to add support for it right now 48 - clearSubsection("moonbase"); 49 - MoonbaseSettingsStore.showOnlyUpdateable = false; 50 }, 51 [] 52 ); 53 54 return ( 55 <> 56 - <div className={`${TitleBarClasses.children} ${Margins.marginBottom20}`}> 57 - <Text className={TitleBarClasses.titleWrapper} variant="heading-lg/semibold" tag="h2"> 58 Moonbase 59 </Text> 60 <Divider /> 61 - <TabBar selectedItem={subsection} onItemSelect={setSubsection} type="top-pill" className={TabBarClasses.tabBar}> 62 {pages.map((page, i) => ( 63 - <TabBar.Item key={page.id} id={i} className={TabBarClasses.item}> 64 {page.name} 65 </TabBar.Item> 66 ))}
··· 1 import React from "@moonlight-mod/wp/react"; 2 import { Text, TabBar } from "@moonlight-mod/wp/discord/components/common/index"; 3 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 4 import { UserSettingsModalStore } from "@moonlight-mod/wp/common_stores"; 5 6 import ExtensionsPage from "./extensions"; 7 import ConfigPage from "./config"; 8 + import AboutPage from "./about"; 9 import Update from "./update"; 10 import RestartAdviceMessage from "./RestartAdvice"; 11 + import { Divider } from "@moonlight-mod/wp/discord/components/common/BaseHeaderBar"; 12 + import HeaderBarClasses from "@moonlight-mod/wp/discord/components/common/HeaderBar.css"; 13 + import PeoplePageClasses from "@moonlight-mod/wp/discord/modules/people/web/PeoplePage.css"; 14 + import UserSettingsModalActionCreators from "@moonlight-mod/wp/discord/actions/UserSettingsModalActionCreators"; 15 + import Margins from "@moonlight-mod/wp/discord/styles/shared/Margins.css"; 16 17 export const pages: { 18 id: string; ··· 28 id: "config", 29 name: "Config", 30 element: ConfigPage 31 + }, 32 + { 33 + id: "about", 34 + name: "About", 35 + element: AboutPage 36 } 37 ]; 38 ··· 40 const subsection = useStateFromStores([UserSettingsModalStore], () => UserSettingsModalStore.getSubsection() ?? 0); 41 const setSubsection = React.useCallback( 42 (to: string) => { 43 + if (subsection !== to) UserSettingsModalActionCreators.setSection("moonbase", to); 44 }, 45 [subsection] 46 ); ··· 48 React.useEffect( 49 () => () => { 50 // Normally there's an onSettingsClose prop you can set but we don't expose it and I don't care enough to add support for it right now 51 + UserSettingsModalActionCreators.clearSubsection("moonbase"); 52 }, 53 [] 54 ); 55 56 return ( 57 <> 58 + <div className={`${HeaderBarClasses.children} ${Margins.marginBottom20}`}> 59 + <Text className={HeaderBarClasses.titleWrapper} variant="heading-lg/semibold" tag="h2"> 60 Moonbase 61 </Text> 62 <Divider /> 63 + <TabBar 64 + selectedItem={subsection} 65 + onItemSelect={setSubsection} 66 + type="top-pill" 67 + className={PeoplePageClasses.tabBar} 68 + > 69 {pages.map((page, i) => ( 70 + <TabBar.Item key={page.id} id={i} className={PeoplePageClasses.item}> 71 {page.name} 72 </TabBar.Item> 73 ))}
+77 -15
packages/core-extensions/src/moonbase/webpackModules/ui/update.tsx
··· 1 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 2 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 3 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 4 import React from "@moonlight-mod/wp/react"; 5 import { UpdateState } from "../../types"; 6 import HelpMessage from "./HelpMessage"; 7 - 8 - const { ThemeDarkIcon, Button } = Components; 9 - 10 - const logger = moonlight.getLogger("moonbase/ui/update"); 11 12 const strings: Record<UpdateState, string> = { 13 [UpdateState.Ready]: "A new version of moonlight is available.", ··· 16 [UpdateState.Failed]: "Failed to update moonlight. Please use the installer instead." 17 }; 18 19 export default function Update() { 20 - const [state, setState] = React.useState(UpdateState.Ready); 21 - const newVersion = useStateFromStores([MoonbaseSettingsStore], () => MoonbaseSettingsStore.newVersion); 22 23 if (newVersion == null) return null; 24 25 return ( 26 <HelpMessage text={strings[state]} className="moonbase-update-section" icon={ThemeDarkIcon}> 27 <div className="moonbase-help-message-buttons"> 28 {state === UpdateState.Installed && ( 29 <Button 30 look={Button.Looks.OUTLINED} ··· 44 size={Button.Sizes.TINY} 45 disabled={state !== UpdateState.Ready} 46 onClick={() => { 47 - setState(UpdateState.Working); 48 - 49 - MoonbaseSettingsStore.updateMoonlight() 50 - .then(() => setState(UpdateState.Installed)) 51 - .catch((e) => { 52 - logger.error(e); 53 - setState(UpdateState.Failed); 54 - }); 55 }} 56 > 57 Update
··· 1 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 2 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 3 import React from "@moonlight-mod/wp/react"; 4 import { UpdateState } from "../../types"; 5 import HelpMessage from "./HelpMessage"; 6 + import { MoonlightBranch } from "@moonlight-mod/types"; 7 + import MarkupUtils from "@moonlight-mod/wp/discord/modules/markup/MarkupUtils"; 8 + import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 9 + import { 10 + Button, 11 + Text, 12 + ModalRoot, 13 + ModalSize, 14 + ModalContent, 15 + ModalHeader, 16 + Heading, 17 + ModalCloseButton, 18 + openModal 19 + } from "@moonlight-mod/wp/discord/components/common/index"; 20 + import MarkupClasses from "@moonlight-mod/wp/discord/modules/messages/web/Markup.css"; 21 + import ThemeDarkIcon from "@moonlight-mod/wp/moonbase_ThemeDarkIcon"; 22 23 const strings: Record<UpdateState, string> = { 24 [UpdateState.Ready]: "A new version of moonlight is available.", ··· 27 [UpdateState.Failed]: "Failed to update moonlight. Please use the installer instead." 28 }; 29 30 + function MoonlightChangelog({ 31 + changelog, 32 + version, 33 + transitionState, 34 + onClose 35 + }: { 36 + changelog: string; 37 + version: string; 38 + transitionState: number | null; 39 + onClose: () => void; 40 + }) { 41 + return ( 42 + <ModalRoot transitionState={transitionState} size={ModalSize.DYNAMIC}> 43 + <ModalHeader> 44 + <Flex.Child grow={1} shrink={1}> 45 + <Heading variant="heading-lg/semibold">moonlight</Heading> 46 + <Text variant="text-xs/normal">{version}</Text> 47 + </Flex.Child> 48 + 49 + <Flex.Child grow={0}> 50 + <ModalCloseButton onClick={onClose} /> 51 + </Flex.Child> 52 + </ModalHeader> 53 + 54 + <ModalContent> 55 + <Text variant="text-md/normal" className={MarkupClasses.markup} style={{ padding: "1rem" }}> 56 + {MarkupUtils.parse(changelog, true, { 57 + allowHeading: true, 58 + allowList: true, 59 + allowLinks: true 60 + })} 61 + </Text> 62 + </ModalContent> 63 + </ModalRoot> 64 + ); 65 + } 66 + 67 export default function Update() { 68 + const [newVersion, state] = useStateFromStores([MoonbaseSettingsStore], () => [ 69 + MoonbaseSettingsStore.newVersion, 70 + MoonbaseSettingsStore.updateState 71 + ]); 72 73 if (newVersion == null) return null; 74 75 return ( 76 <HelpMessage text={strings[state]} className="moonbase-update-section" icon={ThemeDarkIcon}> 77 <div className="moonbase-help-message-buttons"> 78 + {moonlight.branch === MoonlightBranch.STABLE && ( 79 + <Button 80 + look={Button.Looks.OUTLINED} 81 + color={Button.Colors.CUSTOM} 82 + size={Button.Sizes.TINY} 83 + onClick={() => { 84 + fetch(`https://raw.githubusercontent.com/moonlight-mod/moonlight/refs/tags/${newVersion}/CHANGELOG.md`) 85 + .then((r) => r.text()) 86 + .then((changelog) => 87 + openModal((modalProps) => { 88 + return <MoonlightChangelog {...modalProps} changelog={changelog} version={newVersion} />; 89 + }) 90 + ); 91 + }} 92 + > 93 + View changelog 94 + </Button> 95 + )} 96 + 97 {state === UpdateState.Installed && ( 98 <Button 99 look={Button.Looks.OUTLINED} ··· 113 size={Button.Sizes.TINY} 114 disabled={state !== UpdateState.Ready} 115 onClick={() => { 116 + MoonbaseSettingsStore.updateMoonlight(); 117 }} 118 > 119 Update
+3 -6
packages/core-extensions/src/moonbase/webpackModules/updates.tsx
··· 3 import Notices from "@moonlight-mod/wp/notices_notices"; 4 import { MoonlightBranch } from "@moonlight-mod/types"; 5 import React from "@moonlight-mod/wp/react"; 6 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 7 - 8 - const { ThemeDarkIcon } = Components; 9 10 function plural(str: string, num: number) { 11 return `${str}${num > 1 ? "s" : ""}`; ··· 59 { 60 name: "Open Moonbase", 61 onClick: () => { 62 - const { open } = spacepack.findByCode(':"USER_SETTINGS_MODAL_SET_SECTION"')[0].exports.Z; 63 if (MoonbaseSettingsStore.getExtensionConfigRaw<boolean>("moonbase", "sections", false)) { 64 open("moonbase-extensions"); 65 } else { 66 - MoonbaseSettingsStore.showOnlyUpdateable = true; 67 - open("moonbase", 0); 68 } 69 return true; 70 }
··· 3 import Notices from "@moonlight-mod/wp/notices_notices"; 4 import { MoonlightBranch } from "@moonlight-mod/types"; 5 import React from "@moonlight-mod/wp/react"; 6 + import ThemeDarkIcon from "@moonlight-mod/wp/moonbase_ThemeDarkIcon"; 7 8 function plural(str: string, num: number) { 9 return `${str}${num > 1 ? "s" : ""}`; ··· 57 { 58 name: "Open Moonbase", 59 onClick: () => { 60 + const { open } = spacepack.require("discord/actions/UserSettingsModalActionCreators").default; 61 if (MoonbaseSettingsStore.getExtensionConfigRaw<boolean>("moonbase", "sections", false)) { 62 open("moonbase-extensions"); 63 } else { 64 + open("moonbase", "0"); 65 } 66 return true; 67 }
+5
packages/core-extensions/src/moonbase/wp.d.ts
··· 5 declare module "@moonlight-mod/wp/moonbase_stores" { 6 export * from "core-extensions/src/moonbase/webpackModules/stores"; 7 }
··· 5 declare module "@moonlight-mod/wp/moonbase_stores" { 6 export * from "core-extensions/src/moonbase/webpackModules/stores"; 7 } 8 + 9 + declare module "@moonlight-mod/wp/moonbase_ThemeDarkIcon" { 10 + import ThemeDarkIcon from "core-extensions/src/moonbase/webpackModules/ThemeDarkIcon"; 11 + export = ThemeDarkIcon; 12 + }
+141 -1
packages/core-extensions/src/nativeFixes/host.ts
··· 1 import { app, nativeTheme } from "electron"; 2 3 const enabledFeatures = app.commandLine.getSwitchValue("enable-features").split(","); 4 5 moonlightHost.events.on("window-created", function (browserWindow) { ··· 22 23 // already added on Windows, but not on other operating systems 24 app.commandLine.appendSwitch("disable-background-timer-throttling"); 25 } 26 27 if (process.platform === "linux") { ··· 32 if (moonlightHost.getConfigOption<boolean>("nativeFixes", "linuxSpeechDispatcher") ?? true) { 33 app.commandLine.appendSwitch("enable-speech-dispatcher"); 34 } 35 } 36 37 // NOTE: Only tested if this appears on Windows, it should appear on all when 38 // hardware acceleration is disabled 39 const noAccel = app.commandLine.hasSwitch("disable-gpu-compositing"); 40 if ((moonlightHost.getConfigOption<boolean>("nativeFixes", "vaapi") ?? true) && !noAccel) { 41 - if (process.platform === "linux") 42 // These will eventually be renamed https://source.chromium.org/chromium/chromium/src/+/5482210941a94d70406b8da962426e4faca7fce4 43 enabledFeatures.push("VaapiVideoEncoder", "VaapiVideoDecoder", "VaapiVideoDecodeLinuxGL"); 44 } 45 46 app.commandLine.appendSwitch("enable-features", [...new Set(enabledFeatures)].join(","));
··· 1 import { app, nativeTheme } from "electron"; 2 + import * as path from "node:path"; 3 + import * as fs from "node:fs/promises"; 4 + import * as fsSync from "node:fs"; 5 + import { parseTarGzip } from "nanotar"; 6 7 + const logger = moonlightHost.getLogger("nativeFixes/host"); 8 const enabledFeatures = app.commandLine.getSwitchValue("enable-features").split(","); 9 10 moonlightHost.events.on("window-created", function (browserWindow) { ··· 27 28 // already added on Windows, but not on other operating systems 29 app.commandLine.appendSwitch("disable-background-timer-throttling"); 30 + } 31 + 32 + if (moonlightHost.getConfigOption<boolean>("nativeFixes", "vulkan") ?? false) { 33 + enabledFeatures.push("Vulkan", "DefaultANGLEVulkan", "VulkanFromANGLE"); 34 } 35 36 if (process.platform === "linux") { ··· 41 if (moonlightHost.getConfigOption<boolean>("nativeFixes", "linuxSpeechDispatcher") ?? true) { 42 app.commandLine.appendSwitch("enable-speech-dispatcher"); 43 } 44 + 45 + if (moonlightHost.getConfigOption<boolean>("nativeFixes", "linuxHevcSupport") ?? true) { 46 + enabledFeatures.push("PlatformHEVCDecoderSupport"); 47 + } 48 } 49 50 // NOTE: Only tested if this appears on Windows, it should appear on all when 51 // hardware acceleration is disabled 52 const noAccel = app.commandLine.hasSwitch("disable-gpu-compositing"); 53 if ((moonlightHost.getConfigOption<boolean>("nativeFixes", "vaapi") ?? true) && !noAccel) { 54 + if (process.platform === "linux") { 55 // These will eventually be renamed https://source.chromium.org/chromium/chromium/src/+/5482210941a94d70406b8da962426e4faca7fce4 56 enabledFeatures.push("VaapiVideoEncoder", "VaapiVideoDecoder", "VaapiVideoDecodeLinuxGL"); 57 + 58 + if (moonlightHost.getConfigOption<boolean>("nativeFixes", "vaapiIgnoreDriverChecks") ?? false) 59 + enabledFeatures.push("VaapiIgnoreDriverChecks"); 60 + } 61 } 62 63 app.commandLine.appendSwitch("enable-features", [...new Set(enabledFeatures)].join(",")); 64 + 65 + if (process.platform === "linux" && moonlightHost.getConfigOption<boolean>("nativeFixes", "linuxUpdater")) { 66 + const exePath = app.getPath("exe"); 67 + const appName = path.basename(exePath); 68 + const targetDir = path.dirname(exePath); 69 + const { releaseChannel }: { releaseChannel: string } = JSON.parse( 70 + fsSync.readFileSync(path.join(targetDir, "resources", "build_info.json"), "utf8") 71 + ); 72 + 73 + const updaterModule = require(path.join(moonlightHost.asarPath, "app_bootstrap", "hostUpdater.js")); 74 + const updater = updaterModule.constructor; 75 + 76 + async function doUpdate(cb: (percent: number) => void) { 77 + logger.debug("Extracting to", targetDir); 78 + 79 + const exists = (path: string) => 80 + fs 81 + .stat(path) 82 + .then(() => true) 83 + .catch(() => false); 84 + 85 + const url = `https://discord.com/api/download/${releaseChannel}?platform=linux&format=tar.gz`; 86 + const resp = await fetch(url, { 87 + cache: "no-store" 88 + }); 89 + 90 + const reader = resp.body!.getReader(); 91 + const contentLength = parseInt(resp.headers.get("Content-Length") ?? "0"); 92 + logger.info(`Expecting ${contentLength} bytes for the update`); 93 + const bytes = new Uint8Array(contentLength); 94 + let pos = 0; 95 + let lastPercent = 0; 96 + 97 + while (true) { 98 + const { done, value } = await reader.read(); 99 + if (done) { 100 + break; 101 + } else { 102 + bytes.set(value, pos); 103 + pos += value.length; 104 + 105 + const newPercent = Math.floor((pos / contentLength) * 100); 106 + if (lastPercent !== newPercent) { 107 + lastPercent = newPercent; 108 + cb(newPercent); 109 + } 110 + } 111 + } 112 + 113 + const files = await parseTarGzip(bytes); 114 + 115 + for (const file of files) { 116 + if (!file.data) continue; 117 + // @ts-expect-error What do you mean their own types are wrong 118 + if (file.type !== "file") continue; 119 + 120 + // Discord update files are inside of a main "Discord(PTB|Canary)" folder 121 + const filePath = file.name.replace(`${appName}/`, ""); 122 + logger.info("Extracting", filePath); 123 + 124 + let targetFilePath = path.join(targetDir, filePath); 125 + if (filePath === "resources/app.asar") { 126 + // You tried 127 + targetFilePath = path.join(targetDir, "resources", "_app.asar"); 128 + } else if (filePath === appName || filePath === "chrome_crashpad_handler") { 129 + // Can't write over the executable? Just move it! 4head 130 + if (await exists(targetFilePath)) { 131 + await fs.rename(targetFilePath, targetFilePath + ".bak"); 132 + await fs.unlink(targetFilePath + ".bak"); 133 + } 134 + } 135 + const targetFileDir = path.dirname(targetFilePath); 136 + 137 + if (!(await exists(targetFileDir))) await fs.mkdir(targetFileDir, { recursive: true }); 138 + await fs.writeFile(targetFilePath, file.data); 139 + 140 + const mode = file.attrs?.mode; 141 + if (mode != null) { 142 + // Not sure why this slice is needed 143 + await fs.chmod(targetFilePath, mode.slice(-3)); 144 + } 145 + } 146 + 147 + logger.debug("Done updating"); 148 + } 149 + 150 + const realEmit = updater.prototype.emit; 151 + updater.prototype.emit = function (event: string, ...args: any[]) { 152 + // Arrow functions don't bind `this` :D 153 + const call = (event: string, ...args: any[]) => realEmit.call(this, event, ...args); 154 + 155 + if (event === "update-manually") { 156 + const latestVerStr: string = args[0]; 157 + logger.debug("update-manually called, intercepting", latestVerStr); 158 + call("update-available"); 159 + 160 + (async () => { 161 + try { 162 + await doUpdate((progress) => { 163 + call("update-progress", progress); 164 + }); 165 + // Copied from the win32 updater 166 + this.updateVersion = latestVerStr; 167 + call( 168 + "update-downloaded", 169 + {}, 170 + releaseChannel, 171 + latestVerStr, 172 + new Date(), 173 + this.updateUrl, 174 + this.quitAndInstall.bind(this) 175 + ); 176 + } catch (e) { 177 + logger.error("Error updating", e); 178 + } 179 + })(); 180 + 181 + return this; 182 + } else { 183 + return realEmit.call(this, event, ...args); 184 + } 185 + }; 186 + }
+29 -1
packages/core-extensions/src/nativeFixes/manifest.json
··· 4 "meta": { 5 "name": "Native Fixes", 6 "tagline": "Various configurable fixes for Discord and Electron", 7 - "authors": ["Cynosphere", "adryd"], 8 "tags": ["fixes"] 9 }, 10 "environment": "desktop", ··· 23 "type": "boolean", 24 "default": true 25 }, 26 "linuxAutoscroll": { 27 "advice": "restart", 28 "displayName": "Enable middle click autoscroll on Linux", ··· 41 "advice": "restart", 42 "displayName": "Enable VAAPI features on Linux", 43 "description": "Provides hardware accelerated video encode and decode. Has no effect on other operating systems", 44 "type": "boolean", 45 "default": true 46 }
··· 4 "meta": { 5 "name": "Native Fixes", 6 "tagline": "Various configurable fixes for Discord and Electron", 7 + "authors": ["Cynosphere", "adryd", "NotNite"], 8 "tags": ["fixes"] 9 }, 10 "environment": "desktop", ··· 23 "type": "boolean", 24 "default": true 25 }, 26 + "vulkan": { 27 + "advice": "restart", 28 + "displayName": "Enable Vulkan renderer", 29 + "description": "Uses the Vulkan backend for rendering", 30 + "type": "boolean", 31 + "default": false 32 + }, 33 "linuxAutoscroll": { 34 "advice": "restart", 35 "displayName": "Enable middle click autoscroll on Linux", ··· 48 "advice": "restart", 49 "displayName": "Enable VAAPI features on Linux", 50 "description": "Provides hardware accelerated video encode and decode. Has no effect on other operating systems", 51 + "type": "boolean", 52 + "default": true 53 + }, 54 + "vaapiIgnoreDriverChecks": { 55 + "advice": "restart", 56 + "displayName": "Ignore VAAPI driver checks on Linux", 57 + "description": "Forces hardware video acceleration on some graphics drivers at the cost of stability. Has no effect on other operating systems", 58 + "type": "boolean", 59 + "default": false 60 + }, 61 + "linuxUpdater": { 62 + "advice": "restart", 63 + "displayName": "Linux Updater", 64 + "description": "Actually implements updating Discord on Linux. Has no effect on other operating systems", 65 + "type": "boolean", 66 + "default": false 67 + }, 68 + "linuxHevcSupport": { 69 + "advice": "restart", 70 + "displayName": "HEVC support on Linux", 71 + "description": "You might also need to enable Vulkan renderer. Has no effect on other operating systems", 72 "type": "boolean", 73 "default": true 74 }
+3 -3
packages/core-extensions/src/noHideToken/index.ts
··· 2 3 export const patches: Patch[] = [ 4 { 5 - find: "hideToken:function", 6 replace: { 7 - match: /(?<=hideToken:function\(\){)/, 8 - replacement: `return()=>{};` 9 } 10 } 11 ];
··· 2 3 export const patches: Patch[] = [ 4 { 5 + find: "hideToken:()=>", 6 replace: { 7 + match: /hideToken:\(\)=>.+?,/, 8 + replacement: `hideToken:()=>{},` 9 } 10 } 11 ];
+3 -3
packages/core-extensions/src/noTrack/index.ts
··· 2 3 export const patches: Patch[] = [ 4 { 5 - find: "analyticsTrackingStoreMaker:function", 6 replace: { 7 - match: /analyticsTrackingStoreMaker:function\(\){return .+?}/, 8 - replacement: "analyticsTrackingStoreMaker:function(){return ()=>{}}" 9 } 10 }, 11 {
··· 2 3 export const patches: Patch[] = [ 4 { 5 + find: "analyticsTrackingStoreMaker:()=>", 6 replace: { 7 + match: /analyticsTrackingStoreMaker:\(\)=>.+?,/, 8 + replacement: "analyticsTrackingStoreMaker:()=>()=>{}," 9 } 10 }, 11 {
+3 -1
packages/core-extensions/src/noTrack/manifest.json
··· 10 }, 11 "blocked": [ 12 "https://*.discord.com/api/v*/science", 13 - "https://*.discord.com/api/v*/metrics" 14 ] 15 }
··· 10 }, 11 "blocked": [ 12 "https://*.discord.com/api/v*/science", 13 + "https://*.discord.com/api/v*/metrics", 14 + "https://*.discordapp.com/api/v*/science", 15 + "https://*.discordapp.com/api/v*/metrics" 16 ] 17 }
+3 -6
packages/core-extensions/src/notices/webpackModules/component.tsx
··· 1 import React from "@moonlight-mod/wp/react"; 2 import Dispatcher from "@moonlight-mod/wp/discord/Dispatcher"; 3 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 4 import { useStateFromStoresObject } from "@moonlight-mod/wp/discord/packages/flux"; 5 import NoticesStore from "@moonlight-mod/wp/notices_notices"; 6 - import type { Notice } from "@moonlight-mod/types/coreExtensions/notices"; 7 8 - // FIXME: types 9 - const { Notice, NoticeCloseButton, PrimaryCTANoticeButton } = Components; 10 - 11 - function popAndDismiss(notice: Notice) { 12 NoticesStore.popNotice(); 13 if (notice?.onDismiss) { 14 notice.onDismiss();
··· 1 import React from "@moonlight-mod/wp/react"; 2 import Dispatcher from "@moonlight-mod/wp/discord/Dispatcher"; 3 + import { Notice, NoticeCloseButton, PrimaryCTANoticeButton } from "@moonlight-mod/wp/discord/components/common/index"; 4 import { useStateFromStoresObject } from "@moonlight-mod/wp/discord/packages/flux"; 5 import NoticesStore from "@moonlight-mod/wp/notices_notices"; 6 + import type { Notice as NoticeType } from "@moonlight-mod/types/coreExtensions/notices"; 7 8 + function popAndDismiss(notice: NoticeType) { 9 NoticesStore.popNotice(); 10 if (notice?.onDismiss) { 11 notice.onDismiss();
+103 -15
packages/core-extensions/src/quietLoggers/index.ts
··· 3 const notXssDefensesOnly = () => 4 (moonlight.getConfigOption<boolean>("quietLoggers", "xssDefensesOnly") ?? false) === false; 5 6 // These patches MUST run before the simple patches, these are to remove loggers 7 // that end up causing syntax errors by the normal patch 8 const loggerFixes: Patch[] = [ ··· 16 { 17 find: '("GatewaySocket")', 18 replace: { 19 - match: /.\.(info|log)(\(.+?\))(;|,)/g, 20 - replacement: (_, type, body, trail) => `(()=>{})${body}${trail}` 21 } 22 } 23 ]; ··· 28 // Patches to simply remove a logger call 29 const stubPatches = [ 30 // "sh" is not a valid locale. 31 - ["is not a valid locale", /(.)\.error\(""\.concat\((.)," is not a valid locale\."\)\)/g], 32 - ['"[BUILD INFO] Release Channel: "', /new .{1,2}\.Z\(\)\.log\("\[BUILD INFO\] Release Channel: ".+?\)\),/], 33 - ['.APP_NATIVE_CRASH,"Storage"', /console\.log\("AppCrashedFatalReport lastCrash:",.,.\);/], 34 - ['.APP_NATIVE_CRASH,"Storage"', 'console.log("AppCrashedFatalReport: getLastCrash not supported.");'], 35 - ['"[NATIVE INFO] ', /new .{1,2}\.Z\(\)\.log\("\[NATIVE INFO] .+?\)\);/], 36 - ['"Spellchecker"', /.\.info\("Switching to ".+?"\(unavailable\)"\);?/g], 37 - ['throw Error("Messages are still loading.");', /console\.warn\("Unsupported Locale",.\),/], 38 - ["}_dispatchWithDevtools(", /.\.totalTime>.{1,2}&&.\.verbose\(.+?\);/], 39 - ['"NativeDispatchUtils"', /null==.&&.\.warn\("Tried getting Dispatch instance before instantiated"\),/], 40 - ['("DatabaseManager")', /.\.log\("removing database \(user: ".+?\)\),/], 41 [ 42 '"Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. Action: "', 43 - /.\.has\(.\.type\)&&.\.log\(.+?\.type\)\),/ 44 ], 45 - ['console.warn("Window state not initialized"', /console\.warn\("Window state not initialized",.\),/] 46 ]; 47 48 const simplePatches = [ ··· 54 { 55 find: ".Messages.SELF_XSS_HEADER", 56 replace: { 57 - match: /\(null!=.{1,2}&&"0\.0\.0"===.{1,2}\.remoteApp\.getVersion\(\)\)/, 58 replacement: "(true)" 59 } 60 }, 61 ...loggerFixes, 62 ...stubPatches.map((patch) => ({ 63 find: patch[0], ··· 72 replace: { 73 match: patch[0], 74 replacement: patch[1] 75 }, 76 prerequisite: notXssDefensesOnly 77 }))
··· 3 const notXssDefensesOnly = () => 4 (moonlight.getConfigOption<boolean>("quietLoggers", "xssDefensesOnly") ?? false) === false; 5 6 + const silenceDiscordLogger = moonlight.getConfigOption<boolean>("quietLoggers", "silenceDiscordLogger") ?? false; 7 + 8 // These patches MUST run before the simple patches, these are to remove loggers 9 // that end up causing syntax errors by the normal patch 10 const loggerFixes: Patch[] = [ ··· 18 { 19 find: '("GatewaySocket")', 20 replace: { 21 + match: /\i\.(log|info)\(/g, 22 + replacement: "(()=>{})(" 23 + } 24 + }, 25 + { 26 + find: '"_connect called with already existing websocket"', 27 + replace: { 28 + match: /\i\.(log|info|verbose)\(/g, 29 + replacement: "(()=>{})(" 30 } 31 } 32 ]; ··· 37 // Patches to simply remove a logger call 38 const stubPatches = [ 39 // "sh" is not a valid locale. 40 + ["is not a valid locale", /void \i\.error\(""\.concat\(\i," is not a valid locale\."\)\)/g], 41 + ['"[BUILD INFO] Release Channel: "', /new \i\.Z\(\)\.log\("\[BUILD INFO\] Release Channel: ".+?\)\),/], 42 + ['.APP_NATIVE_CRASH,"Storage"', /console\.log\("AppCrashedFatalReport lastCrash:",\i,\i\);/], 43 + ['.APP_NATIVE_CRASH,"Storage"', 'void console.log("AppCrashedFatalReport: getLastCrash not supported.")'], 44 + ['"[NATIVE INFO] ', /new \i\.Z\(\)\.log\("\[NATIVE INFO] .+?\)\);/], 45 + ['"Spellchecker"', /\i\.info\("Switching to ".+?"\(unavailable\)"\);?/g], 46 + ['throw Error("Messages are still loading.");', /console\.warn\("Unsupported Locale",\i\),/], 47 + ["}_dispatchWithDevtools(", /\i\.totalTime>\i&&\i\.verbose\(.+?\);/], 48 + ['"NativeDispatchUtils"', /null==\i&&\i\.warn\("Tried getting Dispatch instance before instantiated"\),/], 49 [ 50 '"Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. Action: "', 51 + /\i\.has\(\i\.type\)&&\i\.log\(.+?\.type\)\),/ 52 + ], 53 + ['console.warn("Window state not initialized"', /console\.warn\("Window state not initialized",\i\),/], 54 + ['.name="MaxListenersExceededWarning",', /(?<=\.length),\i\(\i\)/], 55 + [ 56 + '"The answer for life the universe and everything is:"', 57 + /\i\.info\("The answer for life the universe and everything is:",\i\),/ 58 + ], 59 + [ 60 + '"isLibdiscoreBlockedDomainsEnabled called but libdiscore is not loaded"', 61 + /,\i\.verbose\("isLibdiscoreBlockedDomainsEnabledThisSession: ".concat\(\i\)\)/ 62 + ], 63 + [ 64 + '"Unable to determine render window for element"', 65 + /console\.warn\("Unable to determine render window for element",\i\),/ 66 ], 67 + [ 68 + '"Unable to determine render window for element"', 69 + /console\.warn\('Unable to find element constructor "'\.concat\(\i,'" in'\),\i\),/ 70 + ], 71 + [ 72 + '"[PostMessageTransport] Protocol error: event data should be an Array!"', 73 + /void console\.warn\("\[PostMessageTransport] Protocol error: event data should be an Array!"\)/ 74 + ], 75 + [ 76 + '("ComponentDispatchUtils")', 77 + /new \i\.Z\("ComponentDispatchUtils"\)\.warn\("ComponentDispatch\.resubscribe: Resubscribe without existing subscription",\i\),/ 78 + ] 79 + ]; 80 + 81 + const stripLoggers = [ 82 + '("OverlayRenderStore")', 83 + '("FetchBlockedDomain")', 84 + '="UserSettingsProtoLastWriteTimes",', 85 + '("MessageActionCreators")', 86 + '("Routing/Utils")', 87 + '("DatabaseManager")', 88 + '("KeyboardLayoutMapUtils")', 89 + '("ChannelMessages")', 90 + '("MessageQueue")', 91 + '("RTCLatencyTestManager")', 92 + '("OverlayStoreV3")', 93 + '("OverlayBridgeStore")', 94 + '("AuthenticationStore")', 95 + '("ConnectionStore")', 96 + '"Dispatched INITIAL_GUILD "', 97 + '"handleIdentify called"', 98 + '("Spotify")' 99 ]; 100 101 const simplePatches = [ ··· 107 { 108 find: ".Messages.SELF_XSS_HEADER", 109 replace: { 110 + match: /\(null!=\i&&"0\.0\.0"===\i\.remoteApp\.getVersion\(\)\)/, 111 replacement: "(true)" 112 } 113 }, 114 + { 115 + find: '("ComponentDispatchUtils")', 116 + replace: { 117 + match: 118 + /new \i\.Z\("ComponentDispatchUtils"\)\.warn\("ComponentDispatch\.subscribe: Attempting to add a duplicate listener",\i\)/, 119 + replacement: "void 0" 120 + }, 121 + prerequisite: notXssDefensesOnly 122 + }, 123 + // Highlight.js deprecation warnings 124 + { 125 + find: "Deprecated as of", 126 + replace: { 127 + match: /console\./g, 128 + replacement: "false&&console." 129 + }, 130 + prerequisite: notXssDefensesOnly 131 + }, 132 + // Discord's logger 133 + { 134 + find: "ฮฃ:", 135 + replace: { 136 + match: "for", 137 + replacement: "return;for" 138 + }, 139 + prerequisite: () => silenceDiscordLogger && notXssDefensesOnly() 140 + }, 141 ...loggerFixes, 142 ...stubPatches.map((patch) => ({ 143 find: patch[0], ··· 152 replace: { 153 match: patch[0], 154 replacement: patch[1] 155 + }, 156 + prerequisite: notXssDefensesOnly 157 + })), 158 + ...stripLoggers.map((find) => ({ 159 + find, 160 + replace: { 161 + match: /(\i|this\.logger)\.(log|warn|error|info|verbose)\(/g, 162 + replacement: "(()=>{})(" 163 }, 164 prerequisite: notXssDefensesOnly 165 }))
+7
packages/core-extensions/src/quietLoggers/manifest.json
··· 15 "description": "Only disable self XSS prevention log", 16 "type": "boolean", 17 "default": false 18 } 19 } 20 }
··· 15 "description": "Only disable self XSS prevention log", 16 "type": "boolean", 17 "default": false 18 + }, 19 + "silenceDiscordLogger": { 20 + "advice": "reload", 21 + "displayName": "Silence Discord logger", 22 + "description": "Hides all messages from Discord's logger (the logs that start with purple text in brackets)", 23 + "type": "boolean", 24 + "default": false 25 } 26 } 27 }
+2 -1
packages/core-extensions/src/rocketship/manifest.json
··· 7 "name": "Rocketship", 8 "tagline": "Adds new features when using rocketship", 9 "description": "**This extension only works on Linux when using rocketship:**\nhttps://github.com/moonlight-mod/rocketship\n\nAdds new features to the Discord Linux client with rocketship, such as a better screensharing experience.", 10 - "authors": ["NotNite", "Cynosphere", "adryd"] 11 } 12 }
··· 7 "name": "Rocketship", 8 "tagline": "Adds new features when using rocketship", 9 "description": "**This extension only works on Linux when using rocketship:**\nhttps://github.com/moonlight-mod/rocketship\n\nAdds new features to the Discord Linux client with rocketship, such as a better screensharing experience.", 10 + "authors": ["NotNite", "Cynosphere", "adryd"], 11 + "deprecated": true 12 } 13 }
+1 -1
packages/core-extensions/src/settings/index.ts
··· 12 { 13 find: 'navId:"user-settings-cog",', 14 replace: { 15 - match: /children:\[(.)\.map\(.+?\),children:.\((.)\)/, 16 replacement: (orig, sections, section) => 17 `${orig.replace( 18 /Object\.values\(.\..+?\)/,
··· 12 { 13 find: 'navId:"user-settings-cog",', 14 replace: { 15 + match: /children:\[(\i)\.map\(.+?\),.*?children:\i\((\i)\)/, 16 replacement: (orig, sections, section) => 17 `${orig.replace( 18 /Object\.values\(.\..+?\)/,
+8 -2
packages/core-extensions/src/settings/webpackModules/settings.ts
··· 1 import { SettingsSection, Settings as SettingsType } from "@moonlight-mod/types/coreExtensions/settings"; 2 3 export const Settings: SettingsType = { 4 ourSections: [], 5 sectionNames: [], 6 sectionMenuItems: {}, 7 8 - addSection: (section, label, element, color = null, pos, notice) => { 9 const data: SettingsSection = { 10 section, 11 label, 12 color, 13 element, 14 pos: pos ?? -4, 15 - notice: notice 16 }; 17 18 Settings.ourSections.push(data); ··· 43 44 _mutateSections: (sections) => { 45 for (const section of Settings.ourSections) { 46 sections.splice(section.pos < 0 ? sections.length + section.pos : section.pos, 0, section); 47 } 48
··· 1 import { SettingsSection, Settings as SettingsType } from "@moonlight-mod/types/coreExtensions/settings"; 2 + import UserSettingsModalActionCreators from "@moonlight-mod/wp/discord/actions/UserSettingsModalActionCreators"; 3 4 export const Settings: SettingsType = { 5 ourSections: [], 6 sectionNames: [], 7 sectionMenuItems: {}, 8 9 + addSection: (section, label, element, color = null, pos, notice, onClick) => { 10 const data: SettingsSection = { 11 section, 12 label, 13 color, 14 element, 15 pos: pos ?? -4, 16 + notice: notice, 17 + onClick: onClick ?? (() => UserSettingsModalActionCreators.open(section)) 18 }; 19 20 Settings.ourSections.push(data); ··· 45 46 _mutateSections: (sections) => { 47 for (const section of Settings.ourSections) { 48 + // Discord's `pos` only supports numbers, so lets call the function to get the position. 49 + if (typeof section.pos === "function") { 50 + section.pos = section.pos(sections); 51 + } 52 sections.splice(section.pos < 0 ? sections.length + section.pos : section.pos, 0, section); 53 } 54
+73 -16
packages/core-extensions/src/spacepack/webpackModules/spacepack.ts
··· 37 "module", 38 "exports", 39 "require", 40 - `(${funcStr}).apply(this, arguments)\n` + `//# sourceURL=Webpack-Module-${module}` 41 ) as WebpackModuleFunc; 42 }, 43 44 findByCode: (...args: (string | RegExp)[]) => { 45 - return Object.entries(modules) 46 .filter(([id, mod]) => !args.some((item) => !testFind(mod.toString(), processFind(item)))) 47 .map(([id]) => { 48 //if (!(id in cache)) require(id); ··· 52 try { 53 exports = require(id); 54 } catch (e) { 55 - logger.error(`Error requiring module "${id}": `, e); 56 } 57 58 return { ··· 61 }; 62 }) 63 .filter((item) => item !== null); 64 }, 65 66 findByExports: (...args: string[]) => { ··· 84 }, 85 86 findObjectFromKey: (exports: Record<string, any>, key: string) => { 87 let subKey; 88 if (key.indexOf(".") > -1) { 89 const splitKey = key.split("."); ··· 94 const obj = exports[exportKey]; 95 if (obj && obj[key] !== undefined) { 96 if (subKey) { 97 - if (obj[key][subKey]) return obj; 98 } else { 99 - return obj; 100 } 101 } 102 } 103 - return null; 104 }, 105 106 findObjectFromValue: (exports: Record<string, any>, value: any) => { 107 for (const exportKey in exports) { 108 const obj = exports[exportKey]; 109 // eslint-disable-next-line eqeqeq 110 - if (obj == value) return obj; 111 for (const subKey in obj) { 112 // eslint-disable-next-line eqeqeq 113 if (obj && obj[subKey] == value) { 114 - return obj; 115 } 116 } 117 } 118 - return null; 119 }, 120 121 findObjectFromKeyValuePair: (exports: Record<string, any>, key: string, value: any) => { 122 for (const exportKey in exports) { 123 const obj = exports[exportKey]; 124 // eslint-disable-next-line eqeqeq 125 if (obj && obj[key] == value) { 126 - return obj; 127 } 128 } 129 return null; 130 }, 131 132 findFunctionByStrings: (exports: Record<string, any>, ...strings: (string | RegExp)[]) => { 133 - return ( 134 Object.entries(exports).filter( 135 ([index, func]) => 136 typeof func === "function" && !strings.some((query) => !testFind(func.toString(), processFind(query))) 137 - )?.[0]?.[1] ?? null 138 - ); 139 }, 140 141 lazyLoad: (find: string | RegExp | (string | RegExp)[], chunk: RegExp, module: RegExp) => { 142 const mod = Array.isArray(find) ? spacepack.findByCode(...find) : spacepack.findByCode(find); 143 - if (mod.length < 1) return Promise.reject("Module find failed"); 144 145 const findId = mod[0].id; 146 const findCode = webpackRequire.m[findId].toString().replace(/\n/g, ""); ··· 153 if (match) chunkIds = [...match[0].matchAll(/"(\d+)"/g)].map(([, id]) => id); 154 } 155 156 - if (!chunkIds || chunkIds.length === 0) return Promise.reject("Chunk ID match failed"); 157 158 const moduleId = findCode.match(module)?.[1]; 159 - if (!moduleId) return Promise.reject("Module ID match failed"); 160 161 return Promise.all(chunkIds.map((c) => webpackRequire.e(c))).then(() => webpackRequire(moduleId)); 162 },
··· 37 "module", 38 "exports", 39 "require", 40 + `(${funcStr}).apply(this, arguments)\n` + `//# sourceURL=Webpack-Module/${module.slice(0, 3)}/${module}` 41 ) as WebpackModuleFunc; 42 }, 43 44 findByCode: (...args: (string | RegExp)[]) => { 45 + const ret = Object.entries(modules) 46 .filter(([id, mod]) => !args.some((item) => !testFind(mod.toString(), processFind(item)))) 47 .map(([id]) => { 48 //if (!(id in cache)) require(id); ··· 52 try { 53 exports = require(id); 54 } catch (e) { 55 + logger.error(`findByCode: Error requiring module "${id}": `, args, e); 56 } 57 58 return { ··· 61 }; 62 }) 63 .filter((item) => item !== null); 64 + 65 + if (ret.length === 0) { 66 + logger.warn("findByCode: Got zero results for", args, new Error().stack!.substring(5)); 67 + } 68 + 69 + return ret; 70 }, 71 72 findByExports: (...args: string[]) => { ··· 90 }, 91 92 findObjectFromKey: (exports: Record<string, any>, key: string) => { 93 + let ret = null; 94 let subKey; 95 if (key.indexOf(".") > -1) { 96 const splitKey = key.split("."); ··· 101 const obj = exports[exportKey]; 102 if (obj && obj[key] !== undefined) { 103 if (subKey) { 104 + if (obj[key][subKey]) { 105 + ret = obj; 106 + break; 107 + } 108 } else { 109 + ret = obj; 110 + break; 111 } 112 } 113 } 114 + 115 + if (ret == null) { 116 + logger.warn("Failed to find object by key", key, "in", exports, new Error().stack!.substring(5)); 117 + } 118 + 119 + return ret; 120 }, 121 122 findObjectFromValue: (exports: Record<string, any>, value: any) => { 123 + let ret = null; 124 for (const exportKey in exports) { 125 const obj = exports[exportKey]; 126 // eslint-disable-next-line eqeqeq 127 + if (obj == value) { 128 + ret = obj; 129 + break; 130 + } 131 for (const subKey in obj) { 132 // eslint-disable-next-line eqeqeq 133 if (obj && obj[subKey] == value) { 134 + ret = obj; 135 + break; 136 } 137 } 138 } 139 + 140 + if (ret == null) { 141 + logger.warn("Failed to find object by value", value, "in", exports, new Error().stack!.substring(5)); 142 + } 143 + 144 + return ret; 145 }, 146 147 findObjectFromKeyValuePair: (exports: Record<string, any>, key: string, value: any) => { 148 + let ret = null; 149 for (const exportKey in exports) { 150 const obj = exports[exportKey]; 151 // eslint-disable-next-line eqeqeq 152 if (obj && obj[key] == value) { 153 + ret = obj; 154 + break; 155 } 156 } 157 + 158 + if (ret == null) { 159 + logger.warn( 160 + "Failed to find object by key value pair", 161 + key, 162 + value, 163 + "in", 164 + exports, 165 + new Error().stack!.substring(5) 166 + ); 167 + } 168 + 169 return null; 170 }, 171 172 findFunctionByStrings: (exports: Record<string, any>, ...strings: (string | RegExp)[]) => { 173 + const ret = 174 Object.entries(exports).filter( 175 ([index, func]) => 176 typeof func === "function" && !strings.some((query) => !testFind(func.toString(), processFind(query))) 177 + )?.[0]?.[1] ?? null; 178 + 179 + if (ret == null) { 180 + logger.warn("Failed to find function by strings", strings, "in", exports, new Error().stack!.substring(5)); 181 + } 182 + 183 + return ret; 184 }, 185 186 lazyLoad: (find: string | RegExp | (string | RegExp)[], chunk: RegExp, module: RegExp) => { 187 + chunk = processFind(chunk); 188 + module = processFind(module); 189 + 190 const mod = Array.isArray(find) ? spacepack.findByCode(...find) : spacepack.findByCode(find); 191 + if (mod.length < 1) { 192 + logger.warn("lazyLoad: Module find failed", find, chunk, module, new Error().stack!.substring(5)); 193 + return Promise.reject("Module find failed"); 194 + } 195 196 const findId = mod[0].id; 197 const findCode = webpackRequire.m[findId].toString().replace(/\n/g, ""); ··· 204 if (match) chunkIds = [...match[0].matchAll(/"(\d+)"/g)].map(([, id]) => id); 205 } 206 207 + if (!chunkIds || chunkIds.length === 0) { 208 + logger.warn("lazyLoad: Chunk ID match failed", find, chunk, module, new Error().stack!.substring(5)); 209 + return Promise.reject("Chunk ID match failed"); 210 + } 211 212 const moduleId = findCode.match(module)?.[1]; 213 + if (!moduleId) { 214 + logger.warn("lazyLoad: Module ID match failed", find, chunk, module, new Error().stack!.substring(5)); 215 + return Promise.reject("Module ID match failed"); 216 + } 217 218 return Promise.all(chunkIds.map((c) => webpackRequire.e(c))).then(() => webpackRequire(moduleId)); 219 },
+4 -1
packages/core-extensions/tsconfig.json
··· 1 { 2 - "extends": "../../tsconfig.json" 3 }
··· 1 { 2 + "extends": "../../tsconfig.json", 3 + "compilerOptions": { 4 + "lib": ["ESNext", "DOM", "DOM.Iterable"] 5 + } 6 }
+10 -3
packages/injector/package.json
··· 1 { 2 "name": "@moonlight-mod/injector", 3 "private": true, 4 "dependencies": { 5 - "@moonlight-mod/types": "workspace:*", 6 - "@moonlight-mod/core": "workspace:*" 7 - } 8 }
··· 1 { 2 "name": "@moonlight-mod/injector", 3 "private": true, 4 + "engines": { 5 + "node": ">=22", 6 + "pnpm": ">=10", 7 + "npm": "pnpm", 8 + "yarn": "pnpm" 9 + }, 10 "dependencies": { 11 + "@moonlight-mod/core": "workspace:*", 12 + "@moonlight-mod/types": "workspace:*" 13 + }, 14 + "engineStrict": true 15 }
+37 -14
packages/injector/src/index.ts
··· 76 blockedUrls = compiled; 77 }); 78 79 - function patchCsp(headers: Record<string, string[]>) { 80 - const directives = [ 81 - "script-src", 82 - "style-src", 83 - "connect-src", 84 - "img-src", 85 - "font-src", 86 - "media-src", 87 - "worker-src", 88 - "prefetch-src" 89 - ]; 90 const values = ["*", "blob:", "data:", "'unsafe-inline'", "'unsafe-eval'", "disclip:"]; 91 92 const csp = "content-security-policy"; ··· 106 parts[directive] = values; 107 } 108 109 const stringified = Object.entries<string[]>(parts) 110 .map(([key, value]) => { 111 return `${key} ${value.join(" ")}`; ··· 131 // Event for when a window is created 132 moonlightHost.events.emit("window-created", this, isMainWindow); 133 134 this.webContents.session.webRequest.onHeadersReceived((details, cb) => { 135 if (details.responseHeaders != null) { 136 // Patch CSP so things can use externally hosted assets 137 if (details.resourceType === "mainFrame") { 138 - patchCsp(details.responseHeaders); 139 } 140 141 // Allow plugins to bypass CORS for specific URLs 142 if (corsAllow.some((x) => details.url.startsWith(x))) { 143 - details.responseHeaders["access-control-allow-origin"] = ["*"]; 144 } 145 146 cb({ cancel: false, responseHeaders: details.responseHeaders }); 147 } ··· 160 with esbuild someday). 161 */ 162 if (details.resourceType === "script" && isMainWindow) { 163 - const hasUrl = scriptUrls.some((url) => details.url.includes(url) && !details.url.includes("?inj")); 164 if (hasUrl) blockedScripts.add(details.url); 165 166 if (blockedScripts.size === scriptUrls.length) {
··· 76 blockedUrls = compiled; 77 }); 78 79 + function patchCsp(headers: Record<string, string[]>, extensionCspOverrides: Record<string, string[]>) { 80 + const directives = ["script-src", "style-src", "connect-src", "img-src", "font-src", "media-src", "worker-src"]; 81 const values = ["*", "blob:", "data:", "'unsafe-inline'", "'unsafe-eval'", "disclip:"]; 82 83 const csp = "content-security-policy"; ··· 97 parts[directive] = values; 98 } 99 100 + for (const [directive, urls] of Object.entries(extensionCspOverrides)) { 101 + parts[directive] ??= []; 102 + parts[directive].push(...urls); 103 + } 104 + 105 const stringified = Object.entries<string[]>(parts) 106 .map(([key, value]) => { 107 return `${key} ${value.join(" ")}`; ··· 127 // Event for when a window is created 128 moonlightHost.events.emit("window-created", this, isMainWindow); 129 130 + const extensionCspOverrides: Record<string, string[]> = {}; 131 + 132 + { 133 + const extCsps = moonlightHost.processedExtensions.extensions.map((x) => x.manifest.csp ?? {}); 134 + for (const csp of extCsps) { 135 + for (const [directive, urls] of Object.entries(csp)) { 136 + extensionCspOverrides[directive] ??= []; 137 + extensionCspOverrides[directive].push(...urls); 138 + } 139 + } 140 + } 141 + 142 this.webContents.session.webRequest.onHeadersReceived((details, cb) => { 143 if (details.responseHeaders != null) { 144 // Patch CSP so things can use externally hosted assets 145 if (details.resourceType === "mainFrame") { 146 + patchCsp(details.responseHeaders, extensionCspOverrides); 147 } 148 149 // Allow plugins to bypass CORS for specific URLs 150 if (corsAllow.some((x) => details.url.startsWith(x))) { 151 + if (!details.responseHeaders) details.responseHeaders = {}; 152 + 153 + // Work around HTTP header case sensitivity by reusing the header name if it exists 154 + // https://github.com/moonlight-mod/moonlight/issues/201 155 + const fallback = "access-control-allow-origin"; 156 + const key = Object.keys(details.responseHeaders).find((h) => h.toLowerCase() === fallback) ?? fallback; 157 + details.responseHeaders[key] = ["*"]; 158 } 159 + 160 + moonlightHost.events.emit("headers-received", details, isMainWindow); 161 162 cb({ cancel: false, responseHeaders: details.responseHeaders }); 163 } ··· 176 with esbuild someday). 177 */ 178 if (details.resourceType === "script" && isMainWindow) { 179 + const url = new URL(details.url); 180 + const hasUrl = scriptUrls.some((scriptUrl) => { 181 + return ( 182 + details.url.includes(scriptUrl) && 183 + !url.searchParams.has("inj") && 184 + (url.host.endsWith("discord.com") || url.host.endsWith("discordapp.com")) 185 + ); 186 + }); 187 if (hasUrl) blockedScripts.add(details.url); 188 189 if (blockedScripts.size === scriptUrls.length) {
+8 -1
packages/node-preload/package.json
··· 1 { 2 "name": "@moonlight-mod/node-preload", 3 "private": true, 4 "dependencies": { 5 "@moonlight-mod/core": "workspace:*", 6 "@moonlight-mod/types": "workspace:*" 7 - } 8 }
··· 1 { 2 "name": "@moonlight-mod/node-preload", 3 "private": true, 4 + "engines": { 5 + "node": ">=22", 6 + "pnpm": ">=10", 7 + "npm": "pnpm", 8 + "yarn": "pnpm" 9 + }, 10 "dependencies": { 11 "@moonlight-mod/core": "workspace:*", 12 "@moonlight-mod/types": "workspace:*" 13 + }, 14 + "engineStrict": true 15 }
+52 -37
packages/node-preload/src/index.ts
··· 11 import createFS from "@moonlight-mod/core/fs"; 12 import { registerCors, registerBlocked, getDynamicCors } from "@moonlight-mod/core/cors"; 13 import { getConfig, getConfigOption, getManifest, setConfigOption } from "@moonlight-mod/core/util/config"; 14 15 let initialized = false; 16 let logger: Logger; ··· 51 processedExtensions, 52 nativesCache: {}, 53 isBrowser: false, 54 55 version: MOONLIGHT_VERSION, 56 branch: MOONLIGHT_BRANCH as MoonlightBranch, ··· 62 const manifest = getManifest(extensions, ext); 63 return getConfigOption(ext, name, config, manifest?.settings); 64 }, 65 - setConfigOption(ext, name, value) { 66 setConfigOption(config, ext, name, value); 67 - this.writeConfig(config); 68 }, 69 async writeConfig(newConfig) { 70 await writeConfig(newConfig); 71 config = newConfig; 72 }, 73 74 getNatives: (ext: string) => global.moonlightNode.nativesCache[ext], ··· 129 } 130 } 131 132 - ipcRenderer.on(constants.ipcNodePreloadKickoff, (_, blockedScripts: string[]) => { 133 - (async () => { 134 - try { 135 - await init(); 136 - logger.debug("Blocked scripts:", blockedScripts); 137 138 - const oldPreloadPath: string = ipcRenderer.sendSync(constants.ipcGetOldPreloadPath); 139 - logger.debug("Old preload path:", oldPreloadPath); 140 - if (oldPreloadPath) require(oldPreloadPath); 141 142 - // Do this to get global.DiscordNative assigned 143 - // @ts-expect-error Lying to discord_desktop_core 144 - process.emit("loaded"); 145 146 - function replayScripts() { 147 - const scripts = [...document.querySelectorAll("script")].filter( 148 - (script) => script.src && blockedScripts.some((url) => url.includes(script.src)) 149 - ); 150 151 - blockedScripts.reverse(); 152 - for (const url of blockedScripts) { 153 - if (url.includes("/sentry.")) continue; 154 155 - const script = scripts.find((script) => url.includes(script.src))!; 156 - const newScript = document.createElement("script"); 157 - for (const attr of script.attributes) { 158 - if (attr.name === "src") attr.value += "?inj"; 159 - newScript.setAttribute(attr.name, attr.value); 160 } 161 - script.remove(); 162 - document.documentElement.appendChild(newScript); 163 } 164 - } 165 166 - if (document.readyState === "complete") { 167 - replayScripts(); 168 - } else { 169 - window.addEventListener("load", replayScripts); 170 } 171 - } catch (e) { 172 - logger.error("Error restoring original scripts:", e); 173 - } 174 - })(); 175 - });
··· 11 import createFS from "@moonlight-mod/core/fs"; 12 import { registerCors, registerBlocked, getDynamicCors } from "@moonlight-mod/core/cors"; 13 import { getConfig, getConfigOption, getManifest, setConfigOption } from "@moonlight-mod/core/util/config"; 14 + import { NodeEventPayloads, NodeEventType } from "@moonlight-mod/types/core/event"; 15 + import { createEventEmitter } from "@moonlight-mod/core/util/event"; 16 17 let initialized = false; 18 let logger: Logger; ··· 53 processedExtensions, 54 nativesCache: {}, 55 isBrowser: false, 56 + events: createEventEmitter<NodeEventType, NodeEventPayloads>(), 57 58 version: MOONLIGHT_VERSION, 59 branch: MOONLIGHT_BRANCH as MoonlightBranch, ··· 65 const manifest = getManifest(extensions, ext); 66 return getConfigOption(ext, name, config, manifest?.settings); 67 }, 68 + async setConfigOption(ext, name, value) { 69 setConfigOption(config, ext, name, value); 70 + await this.writeConfig(config); 71 }, 72 async writeConfig(newConfig) { 73 await writeConfig(newConfig); 74 config = newConfig; 75 + this.events.dispatchEvent(NodeEventType.ConfigSaved, newConfig); 76 }, 77 78 getNatives: (ext: string) => global.moonlightNode.nativesCache[ext], ··· 133 } 134 } 135 136 + const oldPreloadPath: string = ipcRenderer.sendSync(constants.ipcGetOldPreloadPath); 137 + const isOverlay = window.location.href.indexOf("discord_overlay") > -1; 138 + 139 + if (isOverlay) { 140 + // The overlay has an inline script tag to call to DiscordNative, so we'll 141 + // just load it immediately. Somehow moonlight still loads in this env, I 142 + // have no idea why - so I suspect it's just forwarding render calls or 143 + // something from the original process 144 + require(oldPreloadPath); 145 + } else { 146 + ipcRenderer.on(constants.ipcNodePreloadKickoff, (_, blockedScripts: string[]) => { 147 + (async () => { 148 + try { 149 + await init(); 150 + logger.debug("Blocked scripts:", blockedScripts); 151 152 + const oldPreloadPath: string = ipcRenderer.sendSync(constants.ipcGetOldPreloadPath); 153 + logger.debug("Old preload path:", oldPreloadPath); 154 + if (oldPreloadPath) require(oldPreloadPath); 155 156 + // Do this to get global.DiscordNative assigned 157 + // @ts-expect-error Lying to discord_desktop_core 158 + process.emit("loaded"); 159 160 + function replayScripts() { 161 + const scripts = [...document.querySelectorAll("script")].filter( 162 + (script) => script.src && blockedScripts.some((url) => url.includes(script.src)) 163 + ); 164 165 + blockedScripts.reverse(); 166 + for (const url of blockedScripts) { 167 + if (url.includes("/sentry.")) continue; 168 169 + const script = scripts.find((script) => url.includes(script.src))!; 170 + const newScript = document.createElement("script"); 171 + for (const attr of script.attributes) { 172 + if (attr.name === "src") attr.value += "?inj"; 173 + newScript.setAttribute(attr.name, attr.value); 174 + } 175 + script.remove(); 176 + document.documentElement.appendChild(newScript); 177 } 178 } 179 180 + if (document.readyState === "complete") { 181 + replayScripts(); 182 + } else { 183 + window.addEventListener("load", replayScripts); 184 + } 185 + } catch (e) { 186 + logger.error("Error restoring original scripts:", e); 187 } 188 + })(); 189 + }); 190 + }
+4 -1
packages/node-preload/tsconfig.json
··· 1 { 2 - "extends": "../../tsconfig.json" 3 }
··· 1 { 2 + "extends": "../../tsconfig.json", 3 + "compilerOptions": { 4 + "lib": ["DOM", "ESNext", "DOM.Iterable"] 5 + } 6 }
+14 -7
packages/types/package.json
··· 1 { 2 "name": "@moonlight-mod/types", 3 - "version": "1.3.5", 4 - "main": "./src/index.ts", 5 - "types": "./src/index.ts", 6 "exports": { 7 ".": "./src/index.ts", 8 "./import": "./src/import.d.ts", 9 "./*": "./src/*.ts" 10 }, 11 "dependencies": { 12 - "@moonlight-mod/lunast": "^1.0.0", 13 - "@moonlight-mod/mappings": "^1.0.10", 14 - "@moonlight-mod/moonmap": "^1.0.3", 15 "@types/react": "^18.3.10", 16 - "csstype": "^3.1.2", 17 "standalone-electron-types": "^1.0.0" 18 } 19 }
··· 1 { 2 "name": "@moonlight-mod/types", 3 + "version": "1.3.17", 4 "exports": { 5 ".": "./src/index.ts", 6 "./import": "./src/import.d.ts", 7 "./*": "./src/*.ts" 8 }, 9 + "main": "./src/index.ts", 10 + "types": "./src/index.ts", 11 + "engineStrict": false, 12 + "engines": { 13 + "node": ">=22", 14 + "pnpm": ">=10", 15 + "npm": "pnpm", 16 + "yarn": "pnpm" 17 + }, 18 "dependencies": { 19 + "@moonlight-mod/lunast": "^1.0.1", 20 + "@moonlight-mod/mappings": "^1.1.25", 21 + "@moonlight-mod/moonmap": "^1.0.5", 22 "@types/react": "^18.3.10", 23 + "csstype": "^3.1.3", 24 "standalone-electron-types": "^1.0.0" 25 } 26 }
+41
packages/types/src/config.ts
··· 33 }; 34 35 export type BooleanSettingType = { 36 type: ExtensionSettingType.Boolean; 37 default?: boolean; 38 }; 39 40 export type NumberSettingType = { 41 type: ExtensionSettingType.Number; 42 default?: number; 43 min?: number; ··· 45 }; 46 47 export type StringSettingType = { 48 type: ExtensionSettingType.String; 49 default?: string; 50 }; 51 52 export type MultilineTextInputSettingType = { 53 type: ExtensionSettingType.MultilineString; 54 default?: string; 55 }; 56 57 export type SelectSettingType = { 58 type: ExtensionSettingType.Select; 59 options: SelectOption[]; 60 default?: string; 61 }; 62 63 export type MultiSelectSettingType = { 64 type: ExtensionSettingType.MultiSelect; 65 options: string[]; 66 default?: string[]; 67 }; 68 69 export type ListSettingType = { 70 type: ExtensionSettingType.List; 71 default?: string[]; 72 }; 73 74 export type DictionarySettingType = { 75 type: ExtensionSettingType.Dictionary; 76 default?: Record<string, string>; 77 }; 78 79 export type CustomSettingType = { 80 type: ExtensionSettingType.Custom; 81 default?: any; 82 }; ··· 88 } 89 90 export type ExtensionSettingsManifest = { 91 displayName?: string; 92 description?: string; 93 advice?: ExtensionSettingsAdvice; 94 } & ( 95 | BooleanSettingType
··· 33 }; 34 35 export type BooleanSettingType = { 36 + /** 37 + * Displays as a simple switch. 38 + */ 39 type: ExtensionSettingType.Boolean; 40 default?: boolean; 41 }; 42 43 export type NumberSettingType = { 44 + /** 45 + * Displays as a simple slider. 46 + */ 47 type: ExtensionSettingType.Number; 48 default?: number; 49 min?: number; ··· 51 }; 52 53 export type StringSettingType = { 54 + /** 55 + * Displays as a single line string input. 56 + */ 57 type: ExtensionSettingType.String; 58 default?: string; 59 }; 60 61 export type MultilineTextInputSettingType = { 62 + /** 63 + * Displays as a multiple line string input. 64 + */ 65 type: ExtensionSettingType.MultilineString; 66 default?: string; 67 }; 68 69 export type SelectSettingType = { 70 + /** 71 + * A dropdown to pick between one of many values. 72 + */ 73 type: ExtensionSettingType.Select; 74 options: SelectOption[]; 75 default?: string; 76 }; 77 78 export type MultiSelectSettingType = { 79 + /** 80 + * A dropdown to pick multiple values. 81 + */ 82 type: ExtensionSettingType.MultiSelect; 83 options: string[]; 84 default?: string[]; 85 }; 86 87 export type ListSettingType = { 88 + /** 89 + * A list of strings that the user can add or remove from. 90 + */ 91 type: ExtensionSettingType.List; 92 default?: string[]; 93 }; 94 95 export type DictionarySettingType = { 96 + /** 97 + * A dictionary (key-value pair) that the user can add or remove from. 98 + */ 99 type: ExtensionSettingType.Dictionary; 100 default?: Record<string, string>; 101 }; 102 103 export type CustomSettingType = { 104 + /** 105 + * A custom component. 106 + * You can use the registerConfigComponent function in the Moonbase API to register a React component to render here. 107 + */ 108 type: ExtensionSettingType.Custom; 109 default?: any; 110 }; ··· 116 } 117 118 export type ExtensionSettingsManifest = { 119 + /** 120 + * A human friendly name for the setting. 121 + */ 122 displayName?: string; 123 + 124 + /** 125 + * A longer description for the setting. 126 + * Markdown is not supported. 127 + */ 128 description?: string; 129 + 130 + /** 131 + * The "advice" to give upon changing this setting. 132 + * Can be configured to reload the client, restart the client, or do nothing. 133 + */ 134 advice?: ExtensionSettingsAdvice; 135 } & ( 136 | BooleanSettingType
+13 -4
packages/types/src/core/event.ts
··· 1 import { WebpackModuleFunc, WebpackRequireType } from "../discord"; 2 3 export interface MoonlightEventEmitter<EventId extends string = string, EventData = Record<EventId, any>> { ··· 6 removeEventListener: <Id extends keyof EventData>(id: Id, cb: (data: EventData[Id]) => void) => void; 7 } 8 9 - export enum EventType { 10 ChunkLoad = "chunkLoad", 11 ExtensionLoad = "extensionLoad" 12 } 13 14 - export type EventPayloads = { 15 - [EventType.ChunkLoad]: { 16 chunkId?: number[]; 17 modules: { [id: string]: WebpackModuleFunc }; 18 require?: (require: WebpackRequireType) => any; 19 }; 20 - [EventType.ExtensionLoad]: string; 21 };
··· 1 + import { Config } from "../config"; 2 import { WebpackModuleFunc, WebpackRequireType } from "../discord"; 3 4 export interface MoonlightEventEmitter<EventId extends string = string, EventData = Record<EventId, any>> { ··· 7 removeEventListener: <Id extends keyof EventData>(id: Id, cb: (data: EventData[Id]) => void) => void; 8 } 9 10 + export enum WebEventType { 11 ChunkLoad = "chunkLoad", 12 ExtensionLoad = "extensionLoad" 13 } 14 15 + export type WebEventPayloads = { 16 + [WebEventType.ChunkLoad]: { 17 chunkId?: number[]; 18 modules: { [id: string]: WebpackModuleFunc }; 19 require?: (require: WebpackRequireType) => any; 20 }; 21 + [WebEventType.ExtensionLoad]: string; 22 + }; 23 + 24 + export enum NodeEventType { 25 + ConfigSaved = "configSaved" 26 + } 27 + 28 + export type NodeEventPayloads = { 29 + [NodeEventType.ConfigSaved]: Config; 30 };
+204
packages/types/src/coreExtensions/commands.ts
···
··· 1 + export const APPLICATION_ID = "-3"; 2 + 3 + export enum CommandType { 4 + CHAT = 1, 5 + MESSAGE = 3, 6 + PRIMARY_ENTRY_POINT = 4, 7 + USER = 2 8 + } 9 + 10 + export enum InputType { 11 + BOT = 3, 12 + BUILT_IN = 0, 13 + BUILT_IN_INTEGRATION = 2, 14 + BUILT_IN_TEXT = 1, 15 + PLACEHOLDER = 4 16 + } 17 + 18 + export enum OptionType { 19 + SUB_COMMAND = 1, 20 + SUB_COMMAND_GROUP = 2, 21 + STRING = 3, 22 + INTEGER = 4, 23 + BOOLEAN = 5, 24 + USER = 6, 25 + CHANNEL = 7, 26 + ROLE = 8, 27 + MENTIONABLE = 9, 28 + NUMBER = 10, 29 + ATTACHMENT = 11 30 + } 31 + 32 + export enum ChannelType { 33 + GUILD_TEXT = 0, 34 + DM = 1, 35 + GUILD_VOICE = 2, 36 + GROUP_DM = 3, 37 + GUILD_CATEGORY = 4, 38 + GUILD_ANNOUNCEMENT = 5, 39 + GUILD_STORE = 6, 40 + ANNOUNCEMENT_THREAD = 10, 41 + PUBLIC_THREAD = 11, 42 + PRIVATE_THREAD = 12, 43 + GUILD_STAGE_VOICE = 13, 44 + GUILD_DIRECTORY = 14, 45 + GUILD_FORUM = 15, 46 + GUILD_MEDIA = 16, 47 + LOBBY = 17, 48 + DM_SDK = 18 49 + } 50 + 51 + export type RegisteredCommandOption = MoonlightCommandOption & { 52 + displayName: string; 53 + displayDescription: string; 54 + }; 55 + 56 + export type CommandOptionChoice<T> = { 57 + name: string; 58 + value: T; 59 + }; 60 + 61 + type CommandOptionBase<T> = { 62 + type: T; 63 + name: string; 64 + description: string; 65 + required?: T extends OptionType.SUB_COMMAND 66 + ? never 67 + : T extends OptionType.SUB_COMMAND_GROUP 68 + ? never 69 + : boolean | undefined; 70 + choices?: T extends OptionType.STRING 71 + ? CommandOptionChoice<string>[] 72 + : T extends OptionType.INTEGER 73 + ? CommandOptionChoice<number>[] 74 + : T extends OptionType.NUMBER 75 + ? CommandOptionChoice<number>[] 76 + : never; 77 + options?: T extends OptionType.SUB_COMMAND 78 + ? MoonlightCommandOption[] 79 + : T extends OptionType.SUB_COMMAND_GROUP 80 + ? MoonlightCommandOption[] 81 + : never; 82 + channelTypes?: T extends OptionType.CHANNEL ? ChannelType[] : never; 83 + minValue?: T extends OptionType.INTEGER ? number : T extends OptionType.NUMBER ? number : never; 84 + maxValue?: T extends OptionType.INTEGER ? number : T extends OptionType.NUMBER ? number : never; 85 + minLength?: T extends OptionType.STRING ? number : never; 86 + maxLength?: T extends OptionType.STRING ? number : never; 87 + }; 88 + 89 + // This is bad lol 90 + export type MoonlightCommandOption = 91 + | CommandOptionBase<OptionType.SUB_COMMAND> 92 + | CommandOptionBase<OptionType.SUB_COMMAND_GROUP> 93 + | CommandOptionBase<OptionType.STRING> 94 + | CommandOptionBase<OptionType.INTEGER> 95 + | CommandOptionBase<OptionType.BOOLEAN> 96 + | CommandOptionBase<OptionType.USER> 97 + | CommandOptionBase<OptionType.CHANNEL> 98 + | CommandOptionBase<OptionType.ROLE> 99 + | CommandOptionBase<OptionType.MENTIONABLE> 100 + | CommandOptionBase<OptionType.NUMBER> 101 + | CommandOptionBase<OptionType.ATTACHMENT>; 102 + 103 + // TODO: types 104 + export type CommandPredicateState = { 105 + channel: any; 106 + guild: any; 107 + }; 108 + 109 + export type RegisteredCommand = { 110 + id: string; 111 + untranslatedName: string; 112 + displayName: string; 113 + type: CommandType; 114 + inputType: InputType; 115 + applicationId: string; // set to -3! 116 + untranslatedDescription: string; 117 + displayDescription: string; 118 + options?: RegisteredCommandOption[]; 119 + predicate?: (state: CommandPredicateState) => boolean; 120 + execute: (options: CommandOption[]) => void; 121 + }; 122 + 123 + export type MoonlightCommand = { 124 + id: string; 125 + description: string; 126 + 127 + /** 128 + * You likely want CHAT 129 + */ 130 + type: CommandType; 131 + 132 + /** 133 + * You likely want BUILT_IN (or BUILT_IN_TEXT if usable with replies) 134 + */ 135 + inputType: InputType; 136 + options?: MoonlightCommandOption[]; 137 + predicate?: (state: CommandPredicateState) => boolean; 138 + execute: (options: CommandOption[]) => void; 139 + }; 140 + 141 + export type CommandOption = { 142 + name: string; 143 + } & ( // TODO: more of these 144 + | { 145 + type: Exclude<OptionType, OptionType.STRING>; 146 + value: any; 147 + } 148 + | { 149 + type: OptionType.STRING; 150 + value: string; 151 + } 152 + | { 153 + type: OptionType.NUMBER | OptionType.INTEGER; 154 + value: number; 155 + } 156 + | { 157 + type: OptionType.BOOLEAN; 158 + value: boolean; 159 + } 160 + | { 161 + type: OptionType.SUB_COMMAND | OptionType.SUB_COMMAND_GROUP; 162 + options: CommandOption[]; 163 + } 164 + ); 165 + 166 + export type AnyScopeRegex = RegExp["exec"] & { 167 + regex: RegExp; 168 + }; 169 + 170 + export type Commands = { 171 + /** 172 + * Register a command in the internal slash command system 173 + */ 174 + registerCommand: (command: MoonlightCommand) => void; 175 + 176 + /** 177 + * Register a legacy command that works via regex 178 + */ 179 + registerLegacyCommand: (id: string, command: LegacyCommand) => void; 180 + 181 + /** 182 + * Creates a regular expression that legacy commands can understand 183 + */ 184 + anyScopeRegex: (regex: RegExp) => AnyScopeRegex; 185 + 186 + /** 187 + * @private 188 + */ 189 + _getCommands: () => RegisteredCommand[]; 190 + }; 191 + 192 + export type LegacyContext = { 193 + channel: any; 194 + isEdit: boolean; 195 + }; 196 + 197 + export type LegacyReturn = { 198 + content: string; 199 + }; 200 + 201 + export type LegacyCommand = { 202 + match?: RegExp | { regex: RegExp } | AnyScopeRegex; 203 + action: (content: string, context: LegacyContext) => LegacyReturn; 204 + };
+33
packages/types/src/coreExtensions/common.ts
···
··· 1 + import type { IconProps, IconSize } from "@moonlight-mod/mappings/discord/components/common/index"; 2 + 3 + export type ErrorBoundaryProps = React.PropsWithChildren<{ 4 + noop?: boolean; 5 + fallback?: React.FC<any>; 6 + message?: string; 7 + }>; 8 + 9 + export type ErrorBoundaryState = { 10 + errored: boolean; 11 + error?: Error; 12 + componentStack?: string; 13 + }; 14 + 15 + export type ErrorBoundary = React.ComponentClass<ErrorBoundaryProps, ErrorBoundaryState>; 16 + 17 + export type ParsedIconProps = { 18 + width: number; 19 + height: number; 20 + fill: string; 21 + className: string; 22 + }; 23 + 24 + export interface Icons { 25 + /** 26 + * Parse icon props into their actual width/height. 27 + * @param props The icon props 28 + */ 29 + parseProps(props?: IconProps): ParsedIconProps; 30 + } 31 + 32 + // Re-export so extension developers don't need to depend on mappings 33 + export type { IconProps, IconSize };
+162
packages/types/src/coreExtensions/componentEditor.ts
···
··· 1 + type Patcher<T> = (elements: React.ReactNode[], props: T) => React.ReactNode[]; 2 + 3 + //#region DM List 4 + export type DMListAnchors = 5 + | "content" 6 + | "favorite-server-indicator" 7 + | "ignored-indicator" 8 + | "blocked-indicator" 9 + | "close-button" 10 + | undefined; 11 + export type DMListDecoratorAnchors = "system-tag" | undefined; 12 + 13 + export enum DMListAnchorIndicies { 14 + content = 0, 15 + "favorite-server-indicator", 16 + "ignored-indicator", 17 + "blocked-indicator", 18 + "close-button" 19 + } 20 + export enum DMListDecoratorAnchorIndicies { 21 + "system-tag" = 0 22 + } 23 + 24 + export type DMListItem = { 25 + component: React.FC<any>; 26 + anchor: DMListAnchors; 27 + before: boolean; 28 + }; 29 + export type DMListDecorator = { 30 + component: React.FC<any>; 31 + anchor: DMListDecoratorAnchors; 32 + before: boolean; 33 + }; 34 + 35 + export type DMList = { 36 + addItem: (id: string, component: React.FC<any>, anchor?: DMListAnchors, before?: boolean) => void; 37 + addDecorator: (id: string, component: React.FC<any>, anchor?: DMListDecoratorAnchors, before?: boolean) => void; 38 + //TODO: fix props type 39 + /** 40 + * @private 41 + */ 42 + _patchItems: Patcher<any>; 43 + /** 44 + * @private 45 + */ 46 + _patchDecorators: Patcher<any>; 47 + }; 48 + //#endregion 49 + 50 + //#region Member List 51 + export type MemberListDecoratorAnchors = "bot-tag" | "owner-crown" | "boost-icon" | undefined; 52 + 53 + export enum MemberListDecoratorAnchorIndicies { 54 + "bot-tag" = 0, 55 + "owner-crown", 56 + "boost-icon" 57 + } 58 + 59 + export type MemberListDecorator = { 60 + component: React.FC<any>; 61 + anchor: MemberListDecoratorAnchors; 62 + before: boolean; 63 + }; 64 + 65 + export type MemberList = { 66 + addItem: (id: string, component: React.FC<any>) => void; 67 + addDecorator: (id: string, component: React.FC<any>, anchor?: MemberListDecoratorAnchors, before?: boolean) => void; 68 + //TODO: fix props type 69 + /** 70 + * @private 71 + */ 72 + _patchItems: Patcher<any>; 73 + /** 74 + * @private 75 + */ 76 + _patchDecorators: Patcher<any>; 77 + }; 78 + //#endregion 79 + 80 + //#region Messages 81 + export type MessageUsernameAnchors = "communication-disabled" | "username" | undefined; 82 + export type MessageUsernameBadgeAnchors = 83 + | "nitro-author" 84 + | "role-icon" 85 + | "new-member" 86 + | "leaderboard-champion" 87 + | "connections" 88 + | undefined; 89 + export type MessageBadgeAnchors = "silent" | "potion" | undefined; 90 + 91 + export type MessageUsername = { 92 + component: React.FC<any>; 93 + anchor: MessageUsernameAnchors; 94 + before: boolean; 95 + }; 96 + export type MessageUsernameBadge = { 97 + component: React.FC<any>; 98 + anchor: MessageUsernameBadgeAnchors; 99 + before: boolean; 100 + }; 101 + export type MessageBadge = { 102 + component: React.FC<any>; 103 + anchor: MessageBadgeAnchors; 104 + before: boolean; 105 + }; 106 + 107 + export enum MessageUsernameIndicies { 108 + "communication-disabled" = 0, 109 + username 110 + } 111 + export enum MessageUsernameBadgeIndicies { 112 + "nitro-author" = 0, 113 + "role-icon", 114 + "new-member", 115 + "leaderboard-champion", 116 + connections 117 + } 118 + export enum MessageBadgeIndicies { 119 + silent = 0, 120 + potion 121 + } 122 + 123 + export type Messages = { 124 + /** 125 + * Adds a component to the username of a message 126 + */ 127 + addToUsername: (id: string, component: React.FC<any>, anchor?: MessageUsernameAnchors, before?: boolean) => void; 128 + /** 129 + * Adds a component to the username badge area of a message (e.g. where role icons/new member badge is) 130 + */ 131 + addUsernameBadge: ( 132 + id: string, 133 + component: React.FC<any>, 134 + anchor?: MessageUsernameBadgeAnchors, 135 + before?: boolean 136 + ) => void; 137 + /** 138 + * Adds a component to the end of a message header (e.g. silent indicator) 139 + */ 140 + addBadge: (id: string, component: React.FC<any>, anchor?: MessageBadgeAnchors, before?: boolean) => void; 141 + /** 142 + * Adds a component to message accessories (e.g. embeds) 143 + */ 144 + addAccessory: (id: string, component: React.FC<any>) => void; 145 + /** 146 + * @private 147 + */ 148 + _patchUsername: Patcher<any>; 149 + /** 150 + * @private 151 + */ 152 + _patchUsernameBadges: Patcher<any>; 153 + /** 154 + * @private 155 + */ 156 + _patchBadges: Patcher<any>; 157 + /** 158 + * @private 159 + */ 160 + _patchAccessories: Patcher<any>; 161 + }; 162 + //#endregion
+1 -1
packages/types/src/coreExtensions/notices.ts
··· 1 - import type { Store } from "@moonlight-mod/mappings/discord/packages/flux"; 2 3 export type NoticeButton = { 4 name: string;
··· 1 + import type { Store } from "@moonlight-mod/mappings/discord/packages/flux/Store"; 2 3 export type NoticeButton = { 4 name: string;
+11 -8
packages/types/src/coreExtensions/settings.ts
··· 1 import React, { ReactElement } from "react"; 2 - import type { Store } from "@moonlight-mod/mappings/discord/packages/flux"; 3 4 export type NoticeProps = { 5 stores: Store<any>[]; ··· 7 }; 8 9 export type SettingsSection = 10 - | { section: "DIVIDER"; pos: number } 11 - | { section: "HEADER"; label: string; pos: number } 12 | { 13 section: string; 14 label: string; 15 color: string | null; 16 element: React.FunctionComponent; 17 - pos: number; 18 notice?: NoticeProps; 19 _moonlight_submenu?: () => ReactElement | ReactElement[]; 20 }; 21 ··· 32 * @param color A color to use for the section 33 * @param pos The position in the settings menu to place the section 34 * @param notice A notice to display when in the section 35 */ 36 addSection: ( 37 section: string, 38 label: string, 39 element: React.FunctionComponent, 40 color?: string | null, 41 - pos?: number, 42 - notice?: NoticeProps 43 ) => void; 44 45 /** ··· 53 * Places a divider in the settings menu. 54 * @param pos The position in the settings menu to place the divider 55 */ 56 - addDivider: (pos: number | null) => void; 57 58 /** 59 * Places a header in the settings menu. 60 * @param pos The position in the settings menu to place the header 61 */ 62 - addHeader: (label: string, pos: number | null) => void; 63 64 /** 65 * @private
··· 1 import React, { ReactElement } from "react"; 2 + import type { Store } from "@moonlight-mod/mappings/discord/packages/flux/Store"; 3 4 export type NoticeProps = { 5 stores: Store<any>[]; ··· 7 }; 8 9 export type SettingsSection = 10 + | { section: "DIVIDER"; pos: number | ((sections: SettingsSection[]) => number) } 11 + | { section: "HEADER"; label: string; pos: number | ((sections: SettingsSection[]) => number) } 12 | { 13 section: string; 14 label: string; 15 color: string | null; 16 element: React.FunctionComponent; 17 + pos: number | ((sections: SettingsSection[]) => number); 18 notice?: NoticeProps; 19 + onClick?: () => void; 20 _moonlight_submenu?: () => ReactElement | ReactElement[]; 21 }; 22 ··· 33 * @param color A color to use for the section 34 * @param pos The position in the settings menu to place the section 35 * @param notice A notice to display when in the section 36 + * @param onClick A custom action to execute when clicked from the context menu 37 */ 38 addSection: ( 39 section: string, 40 label: string, 41 element: React.FunctionComponent, 42 color?: string | null, 43 + pos?: number | ((sections: SettingsSection[]) => number), 44 + notice?: NoticeProps, 45 + onClick?: () => void 46 ) => void; 47 48 /** ··· 56 * Places a divider in the settings menu. 57 * @param pos The position in the settings menu to place the divider 58 */ 59 + addDivider: (pos: number | ((sections: SettingsSection[]) => number) | null) => void; 60 61 /** 62 * Places a header in the settings menu. 63 * @param pos The position in the settings menu to place the header 64 */ 65 + addHeader: (label: string, pos: number | ((sections: SettingsSection[]) => number) | null) => void; 66 67 /** 68 * @private
+1
packages/types/src/coreExtensions/spacepack.ts
··· 18 19 /** 20 * Find Webpack modules based on their exports. 21 * @param args A list of finds to match exports against 22 * @returns The Webpack modules, if found 23 */
··· 18 19 /** 20 * Find Webpack modules based on their exports. 21 + * @deprecated This has race conditions. Consider using findByCode instead. 22 * @param args A list of finds to match exports against 23 * @returns The Webpack modules, if found 24 */
+3
packages/types/src/coreExtensions.ts
··· 5 export * as Notices from "./coreExtensions/notices"; 6 export * as Moonbase from "./coreExtensions/moonbase"; 7 export * as AppPanels from "./coreExtensions/appPanels";
··· 5 export * as Notices from "./coreExtensions/notices"; 6 export * as Moonbase from "./coreExtensions/moonbase"; 7 export * as AppPanels from "./coreExtensions/appPanels"; 8 + export * as Commands from "./coreExtensions/commands"; 9 + export * as ComponentEditor from "./coreExtensions/componentEditor"; 10 + export * as Common from "./coreExtensions/common";
+12
packages/types/src/discord/require.ts
··· 1 import { AppPanels } from "../coreExtensions/appPanels"; 2 import { ContextMenu, EvilItemParser } from "../coreExtensions/contextMenu"; 3 import { Markdown } from "../coreExtensions/markdown"; 4 import { Moonbase } from "../coreExtensions/moonbase"; ··· 9 declare function WebpackRequire(id: string): any; 10 11 declare function WebpackRequire(id: "appPanels_appPanels"): AppPanels; 12 13 declare function WebpackRequire(id: "contextMenu_evilMenu"): EvilItemParser; 14 declare function WebpackRequire(id: "contextMenu_contextMenu"): ContextMenu;
··· 1 import { AppPanels } from "../coreExtensions/appPanels"; 2 + import { Commands } from "../coreExtensions/commands"; 3 + import { ErrorBoundary, Icons } from "../coreExtensions/common"; 4 + import { DMList, MemberList, Messages } from "../coreExtensions/componentEditor"; 5 import { ContextMenu, EvilItemParser } from "../coreExtensions/contextMenu"; 6 import { Markdown } from "../coreExtensions/markdown"; 7 import { Moonbase } from "../coreExtensions/moonbase"; ··· 12 declare function WebpackRequire(id: string): any; 13 14 declare function WebpackRequire(id: "appPanels_appPanels"): AppPanels; 15 + 16 + declare function WebpackRequire(id: "commands_commands"): Commands; 17 + 18 + declare function WebpackRequire(id: "common_ErrorBoundary"): ErrorBoundary; 19 + declare function WebpackRequire(id: "common_icons"): Icons; 20 + 21 + declare function WebpackRequire(id: "componentEditor_dmList"): DMList; 22 + declare function WebpackRequire(id: "componentEditor_memberList"): MemberList; 23 + declare function WebpackRequire(id: "componentEditor_messages"): Messages; 24 25 declare function WebpackRequire(id: "contextMenu_evilMenu"): EvilItemParser; 26 declare function WebpackRequire(id: "contextMenu_contextMenu"): ContextMenu;
+101 -1
packages/types/src/extension.ts
··· 28 }; 29 30 export type ExtensionManifest = { 31 id: string; 32 version?: string; 33 apiLevel?: number; 34 environment?: ExtensionEnvironment; 35 36 meta?: { 37 name?: string; 38 tagline?: string; 39 description?: string; 40 authors?: ExtensionAuthor[]; 41 - deprecated?: boolean; 42 tags?: ExtensionTag[]; 43 source?: string; 44 changelog?: string; 45 }; 46 47 dependencies?: string[]; 48 suggested?: string[]; 49 incompatible?: string[]; 50 51 settings?: Record<string, ExtensionSettingsManifest>; 52 53 cors?: string[]; 54 blocked?: string[]; 55 }; 56 57 export enum ExtensionEnvironment { 58 Both = "both", 59 Desktop = "desktop", 60 Web = "web" 61 } 62
··· 28 }; 29 30 export type ExtensionManifest = { 31 + $schema?: string; 32 + 33 + /** 34 + * A unique identifier for your extension. 35 + */ 36 id: string; 37 + 38 + /** 39 + * A version string for your extension - doesn't need to follow a specific format. Required for publishing. 40 + */ 41 version?: string; 42 + 43 + /** 44 + * The API level this extension targets. If it does not match the current version, the extension will not be loaded. 45 + */ 46 apiLevel?: number; 47 + 48 + /** 49 + * Which environment this extension is capable of running in. 50 + */ 51 environment?: ExtensionEnvironment; 52 53 + /** 54 + * Metadata about your extension for use in Moonbase. 55 + */ 56 meta?: { 57 + /** 58 + * A human friendly name for your extension as a proper noun. 59 + */ 60 name?: string; 61 + 62 + /** 63 + * A short tagline that appears below the name. 64 + */ 65 tagline?: string; 66 + 67 + /** 68 + * A longer description that can use Markdown. 69 + */ 70 description?: string; 71 + 72 + /** 73 + * List of authors that worked on this extension - accepts string or object with ID. 74 + */ 75 authors?: ExtensionAuthor[]; 76 + 77 + /** 78 + * A list of tags that are relevant to the extension. 79 + */ 80 tags?: ExtensionTag[]; 81 + 82 + /** 83 + * The URL to the source repository. 84 + */ 85 source?: string; 86 + 87 + /** 88 + * A donation link (or other method of support). If you don't want financial contributions, consider putting your favorite charity here! 89 + */ 90 + donate?: string; 91 + 92 + /** 93 + * A changelog to show in Moonbase. 94 + * Moonbase will show the changelog for the latest version, even if it is not installed. 95 + */ 96 changelog?: string; 97 + 98 + /** 99 + * Whether the extension is deprecated and no longer receiving updates. 100 + */ 101 + deprecated?: boolean; 102 }; 103 104 + /** 105 + * A list of extension IDs that are required for the extension to load. 106 + */ 107 dependencies?: string[]; 108 + 109 + /** 110 + * A list of extension IDs that the user may want to install. 111 + */ 112 suggested?: string[]; 113 + 114 + /** 115 + * A list of extension IDs that the extension is incompatible with. 116 + * If two incompatible extensions are enabled, one of them will not load. 117 + */ 118 incompatible?: string[]; 119 120 + /** 121 + * A list of settings for your extension, where the key is the settings ID. 122 + */ 123 settings?: Record<string, ExtensionSettingsManifest>; 124 125 + /** 126 + * A list of URLs to bypass CORS for. 127 + * This is implemented by checking if the start of the URL matches. 128 + * @example https://moonlight-mod.github.io/ 129 + */ 130 cors?: string[]; 131 + 132 + /** 133 + * A list of URLs to block all requests to. 134 + * This is implemented by checking if the start of the URL matches. 135 + * @example https://moonlight-mod.github.io/ 136 + */ 137 blocked?: string[]; 138 + 139 + /** 140 + * A mapping from CSP directives to URLs to allow. 141 + * @example { "script-src": ["https://example.com"] } 142 + */ 143 + csp?: Record<string, string[]>; 144 }; 145 146 export enum ExtensionEnvironment { 147 + /** 148 + * The extension will run on both platforms, the host/native modules MAY be loaded 149 + */ 150 Both = "both", 151 + 152 + /** 153 + * Extension will run on desktop only, the host/native modules are guaranteed to load 154 + */ 155 Desktop = "desktop", 156 + 157 + /** 158 + * Currently equivalent to Both 159 + */ 160 Web = "web" 161 } 162
+1
packages/types/src/fs.ts
··· 15 16 join: (...parts: string[]) => string; 17 dirname: (path: string) => string; 18 };
··· 15 16 join: (...parts: string[]) => string; 17 dirname: (path: string) => string; 18 + basename: (path: string) => string; 19 };
+11 -4
packages/types/src/globals.ts
··· 4 import type EventEmitter from "events"; 5 import type LunAST from "@moonlight-mod/lunast"; 6 import type Moonmap from "@moonlight-mod/moonmap"; 7 - import type { EventPayloads, EventType, MoonlightEventEmitter } from "./core/event"; 8 - import { MoonlightFS } from "./fs"; 9 10 export type MoonlightHost = { 11 config: Config; ··· 34 processedExtensions: ProcessedExtensions; 35 nativesCache: Record<string, any>; 36 isBrowser: boolean; 37 38 version: string; 39 branch: MoonlightBranch; 40 41 getConfig: (ext: string) => ConfigExtension["config"]; 42 getConfigOption: <T>(ext: string, name: string) => T | undefined; 43 - setConfigOption: <T>(ext: string, name: string, value: T) => void; 44 writeConfig: (config: Config) => Promise<void>; 45 46 getNatives: (ext: string) => any | undefined; ··· 60 unpatched: Set<IdentifiedPatch>; 61 pendingModules: Set<IdentifiedWebpackModule>; 62 enabledExtensions: Set<string>; 63 - events: MoonlightEventEmitter<EventType, EventPayloads>; 64 patchingInternals: { 65 onModuleLoad: (moduleId: string | string[], callback: (moduleId: string) => void) => void; 66 registerPatch: (patch: IdentifiedPatch) => void;
··· 4 import type EventEmitter from "events"; 5 import type LunAST from "@moonlight-mod/lunast"; 6 import type Moonmap from "@moonlight-mod/moonmap"; 7 + import type { 8 + WebEventPayloads, 9 + WebEventType, 10 + MoonlightEventEmitter, 11 + NodeEventType, 12 + NodeEventPayloads 13 + } from "./core/event"; 14 + import type { MoonlightFS } from "./fs"; 15 16 export type MoonlightHost = { 17 config: Config; ··· 40 processedExtensions: ProcessedExtensions; 41 nativesCache: Record<string, any>; 42 isBrowser: boolean; 43 + events: MoonlightEventEmitter<NodeEventType, NodeEventPayloads>; 44 45 version: string; 46 branch: MoonlightBranch; 47 48 getConfig: (ext: string) => ConfigExtension["config"]; 49 getConfigOption: <T>(ext: string, name: string) => T | undefined; 50 + setConfigOption: <T>(ext: string, name: string, value: T) => Promise<void>; 51 writeConfig: (config: Config) => Promise<void>; 52 53 getNatives: (ext: string) => any | undefined; ··· 67 unpatched: Set<IdentifiedPatch>; 68 pendingModules: Set<IdentifiedWebpackModule>; 69 enabledExtensions: Set<string>; 70 + events: MoonlightEventEmitter<WebEventType, WebEventPayloads>; 71 patchingInternals: { 72 onModuleLoad: (moduleId: string | string[], callback: (moduleId: string) => void) => void; 73 registerPatch: (patch: IdentifiedPatch) => void;
+32
packages/types/src/import.d.ts
··· 4 export = AppPanels; 5 } 6 7 declare module "@moonlight-mod/wp/common_stores"; 8 9 declare module "@moonlight-mod/wp/contextMenu_evilMenu" { 10 import { CoreExtensions } from "@moonlight-mod/types";
··· 4 export = AppPanels; 5 } 6 7 + declare module "@moonlight-mod/wp/commands_commands" { 8 + import { CoreExtensions } from "@moonlight-mod/types"; 9 + export const commands: CoreExtensions.Commands.Commands; 10 + export default commands; 11 + } 12 + 13 + declare module "@moonlight-mod/wp/common_ErrorBoundary" { 14 + import { CoreExtensions } from "@moonlight-mod/types"; 15 + const ErrorBoundary: CoreExtensions.Common.ErrorBoundary; 16 + export = ErrorBoundary; 17 + } 18 + declare module "@moonlight-mod/wp/common_icons" { 19 + import { CoreExtensions } from "@moonlight-mod/types"; 20 + export const icons: CoreExtensions.Common.Icons; 21 + export default icons; 22 + } 23 declare module "@moonlight-mod/wp/common_stores"; 24 + 25 + declare module "@moonlight-mod/wp/componentEditor_dmList" { 26 + import { CoreExtensions } from "@moonlight-mod/types"; 27 + export const dmList: CoreExtensions.ComponentEditor.DMList; 28 + export default dmList; 29 + } 30 + declare module "@moonlight-mod/wp/componentEditor_memberList" { 31 + import { CoreExtensions } from "@moonlight-mod/types"; 32 + export const memberList: CoreExtensions.ComponentEditor.MemberList; 33 + export default memberList; 34 + } 35 + declare module "@moonlight-mod/wp/componentEditor_messages" { 36 + import { CoreExtensions } from "@moonlight-mod/types"; 37 + export const message: CoreExtensions.ComponentEditor.Messages; 38 + export default message; 39 + } 40 41 declare module "@moonlight-mod/wp/contextMenu_evilMenu" { 42 import { CoreExtensions } from "@moonlight-mod/types";
+1
packages/types/src/index.ts
··· 32 var moonlightNode: MoonlightNode; 33 var moonlightNodeSandboxed: MoonlightNodeSandboxed; 34 var moonlight: MoonlightWeb; 35 36 var _moonlightBrowserInit: undefined | (() => Promise<void>); 37 var _moonlightWebLoad: undefined | (() => Promise<void>);
··· 32 var moonlightNode: MoonlightNode; 33 var moonlightNodeSandboxed: MoonlightNodeSandboxed; 34 var moonlight: MoonlightWeb; 35 + var _moonlight_coreExtensionsStr: string; 36 37 var _moonlightBrowserInit: undefined | (() => Promise<void>); 38 var _moonlightWebLoad: undefined | (() => Promise<void>);
+841 -25
packages/types/src/mappings.d.ts
··· 1 // auto-generated 2 declare module "@moonlight-mod/wp/discord/Dispatcher" { 3 import { MappedModules } from "@moonlight-mod/mappings"; 4 - const _: MappedModules["discord/Dispatcher"]; 5 - export = _; 6 } 7 8 declare module "@moonlight-mod/wp/discord/actions/ContextMenuActionCreators" { 9 import { MappedModules } from "@moonlight-mod/mappings"; 10 - const _: MappedModules["discord/actions/ContextMenuActionCreators"]; 11 - export = _; 12 } 13 14 declare module "@moonlight-mod/wp/discord/components/common/index" { 15 import { MappedModules } from "@moonlight-mod/mappings"; 16 - const _: MappedModules["discord/components/common/index"]; 17 - export = _; 18 } 19 20 - declare module "@moonlight-mod/wp/discord/modules/guild_settings/IntegrationCard.css" { 21 import { MappedModules } from "@moonlight-mod/mappings"; 22 - const _: MappedModules["discord/modules/guild_settings/IntegrationCard.css"]; 23 - export = _; 24 } 25 26 declare module "@moonlight-mod/wp/discord/modules/markup/MarkupUtils" { 27 import { MappedModules } from "@moonlight-mod/mappings"; 28 - const _: MappedModules["discord/modules/markup/MarkupUtils"]; 29 - export = _; 30 } 31 32 - declare module "@moonlight-mod/wp/discord/modules/user_settings/web/openUserSettings" { 33 import { MappedModules } from "@moonlight-mod/mappings"; 34 - const _: MappedModules["discord/modules/user_settings/web/openUserSettings"]; 35 - export = _; 36 } 37 38 declare module "@moonlight-mod/wp/discord/packages/flux" { 39 import { MappedModules } from "@moonlight-mod/mappings"; 40 - const _: MappedModules["discord/packages/flux"]; 41 - export = _; 42 } 43 44 declare module "@moonlight-mod/wp/discord/uikit/Flex" { 45 import { MappedModules } from "@moonlight-mod/mappings"; 46 - const _: MappedModules["discord/uikit/Flex"]; 47 - export = _; 48 } 49 50 declare module "@moonlight-mod/wp/discord/utils/ClipboardUtils" { 51 import { MappedModules } from "@moonlight-mod/mappings"; 52 - const _: MappedModules["discord/utils/ClipboardUtils"]; 53 - export = _; 54 } 55 56 declare module "@moonlight-mod/wp/discord/utils/HTTPUtils" { 57 import { MappedModules } from "@moonlight-mod/mappings"; 58 - const _: MappedModules["discord/utils/HTTPUtils"]; 59 - export = _; 60 } 61 62 declare module "@moonlight-mod/wp/discord/utils/NativeUtils" { 63 import { MappedModules } from "@moonlight-mod/mappings"; 64 - const _: MappedModules["discord/utils/NativeUtils"]; 65 - export = _; 66 } 67 68 declare module "@moonlight-mod/wp/react" { 69 import { MappedModules } from "@moonlight-mod/mappings"; 70 - const _: MappedModules["react"]; 71 export = _; 72 }
··· 1 // auto-generated 2 + declare module "@moonlight-mod/wp/chroma-js" {} 3 + 4 + declare module "@moonlight-mod/wp/classnames" { 5 + import { MappedModules } from "@moonlight-mod/mappings"; 6 + const _default: MappedModules["classnames"]["default"]; 7 + export default _default; 8 + } 9 + 10 + declare module "@moonlight-mod/wp/dependency-graph" { 11 + import { MappedModules } from "@moonlight-mod/mappings"; 12 + export const DepGraph: MappedModules["dependency-graph"]["DepGraph"]; 13 + } 14 + 15 + declare module "@moonlight-mod/wp/discord/Constants" { 16 + import { MappedModules } from "@moonlight-mod/mappings"; 17 + export const ActivityFlags: MappedModules["discord/Constants"]["ActivityFlags"]; 18 + export const ActivityTypes: MappedModules["discord/Constants"]["ActivityTypes"]; 19 + export const AnalyticsLocations: MappedModules["discord/Constants"]["AnalyticsLocations"]; 20 + export const ChannelLayouts: MappedModules["discord/Constants"]["ChannelLayouts"]; 21 + export const ChannelModes: MappedModules["discord/Constants"]["ChannelModes"]; 22 + export const ChannelTypes: MappedModules["discord/Constants"]["ChannelTypes"]; 23 + export const ChannelStreamTypes: MappedModules["discord/Constants"]["ChannelStreamTypes"]; 24 + export const ComponentActions: MappedModules["discord/Constants"]["ComponentActions"]; 25 + export const DEFAULT_ROLE_COLOR: MappedModules["discord/Constants"]["DEFAULT_ROLE_COLOR"]; 26 + export const Endpoints: MappedModules["discord/Constants"]["Endpoints"]; 27 + export const MessageFlags: MappedModules["discord/Constants"]["MessageFlags"]; 28 + export const MessageTypes: MappedModules["discord/Constants"]["MessageTypes"]; 29 + export const Permissions: MappedModules["discord/Constants"]["Permissions"]; 30 + export const PlatformTypes: MappedModules["discord/Constants"]["PlatformTypes"]; 31 + export const RelationshipTypes: MappedModules["discord/Constants"]["RelationshipTypes"]; 32 + export const Routes: MappedModules["discord/Constants"]["Routes"]; 33 + export const StatusTypes: MappedModules["discord/Constants"]["StatusTypes"]; 34 + export const Themes: MappedModules["discord/Constants"]["Themes"]; 35 + export const UserSettingsSections: MappedModules["discord/Constants"]["UserSettingsSections"]; 36 + export const UserFlags: MappedModules["discord/Constants"]["UserFlags"]; 37 + } 38 + 39 declare module "@moonlight-mod/wp/discord/Dispatcher" { 40 import { MappedModules } from "@moonlight-mod/mappings"; 41 + const _default: MappedModules["discord/Dispatcher"]["default"]; 42 + export default _default; 43 } 44 45 declare module "@moonlight-mod/wp/discord/actions/ContextMenuActionCreators" { 46 import { MappedModules } from "@moonlight-mod/mappings"; 47 + export const closeContextMenu: MappedModules["discord/actions/ContextMenuActionCreators"]["closeContextMenu"]; 48 + export const openContextMenu: MappedModules["discord/actions/ContextMenuActionCreators"]["openContextMenu"]; 49 + export const openContextMenuLazy: MappedModules["discord/actions/ContextMenuActionCreators"]["openContextMenuLazy"]; 50 + } 51 + 52 + declare module "@moonlight-mod/wp/discord/actions/UserSettingsModalActionCreators" { 53 + import { MappedModules } from "@moonlight-mod/mappings"; 54 + const _default: MappedModules["discord/actions/UserSettingsModalActionCreators"]["default"]; 55 + export default _default; 56 + } 57 + 58 + declare module "@moonlight-mod/wp/discord/common/AppStartPerformance" { 59 + import { MappedModules } from "@moonlight-mod/mappings"; 60 + const _default: MappedModules["discord/common/AppStartPerformance"]["default"]; 61 + export default _default; 62 + } 63 + 64 + declare module "@moonlight-mod/wp/discord/components/common/Alerts" { 65 + import { MappedModules } from "@moonlight-mod/mappings"; 66 + const _default: MappedModules["discord/components/common/Alerts"]["default"]; 67 + export default _default; 68 + } 69 + 70 + declare module "@moonlight-mod/wp/discord/components/common/BaseHeaderBar" { 71 + import { MappedModules } from "@moonlight-mod/mappings"; 72 + export const Icon: MappedModules["discord/components/common/BaseHeaderBar"]["Icon"]; 73 + export const Divider: MappedModules["discord/components/common/BaseHeaderBar"]["Divider"]; 74 + const _default: MappedModules["discord/components/common/BaseHeaderBar"]["default"]; 75 + export default _default; 76 + } 77 + 78 + declare module "@moonlight-mod/wp/discord/components/common/Card" { 79 + import { MappedModules } from "@moonlight-mod/mappings"; 80 + const _default: MappedModules["discord/components/common/Card"]["default"]; 81 + export default _default; 82 + export const Types: MappedModules["discord/components/common/Card"]["Types"]; 83 + } 84 + 85 + declare module "@moonlight-mod/wp/discord/components/common/FileUpload" { 86 + import { MappedModules } from "@moonlight-mod/mappings"; 87 + const _default: MappedModules["discord/components/common/FileUpload"]["default"]; 88 + export default _default; 89 + } 90 + 91 + declare module "@moonlight-mod/wp/discord/components/common/FormSwitch.css" { 92 + import { MappedModules } from "@moonlight-mod/mappings"; 93 + export const container: MappedModules["discord/components/common/FormSwitch.css"]["container"]; 94 + export const labelRow: MappedModules["discord/components/common/FormSwitch.css"]["labelRow"]; 95 + export const control: MappedModules["discord/components/common/FormSwitch.css"]["control"]; 96 + export const disabled: MappedModules["discord/components/common/FormSwitch.css"]["disabled"]; 97 + export const title: MappedModules["discord/components/common/FormSwitch.css"]["title"]; 98 + export const note: MappedModules["discord/components/common/FormSwitch.css"]["note"]; 99 + export const disabledText: MappedModules["discord/components/common/FormSwitch.css"]["disabledText"]; 100 + export const dividerDefault: MappedModules["discord/components/common/FormSwitch.css"]["dividerDefault"]; 101 + } 102 + 103 + declare module "@moonlight-mod/wp/discord/components/common/HeaderBar.css" { 104 + import { MappedModules } from "@moonlight-mod/mappings"; 105 + export const caret: MappedModules["discord/components/common/HeaderBar.css"]["caret"]; 106 + export const children: MappedModules["discord/components/common/HeaderBar.css"]["children"]; 107 + export const clickable: MappedModules["discord/components/common/HeaderBar.css"]["clickable"]; 108 + export const container: MappedModules["discord/components/common/HeaderBar.css"]["container"]; 109 + export const divider: MappedModules["discord/components/common/HeaderBar.css"]["divider"]; 110 + export const dot: MappedModules["discord/components/common/HeaderBar.css"]["dot"]; 111 + export const hamburger: MappedModules["discord/components/common/HeaderBar.css"]["hamburger"]; 112 + export const icon: MappedModules["discord/components/common/HeaderBar.css"]["icon"]; 113 + export const iconBadge: MappedModules["discord/components/common/HeaderBar.css"]["iconBadge"]; 114 + export const iconBadgeBottom: MappedModules["discord/components/common/HeaderBar.css"]["iconBadgeBottom"]; 115 + export const iconBadgeTop: MappedModules["discord/components/common/HeaderBar.css"]["iconBadgeTop"]; 116 + export const iconWrapper: MappedModules["discord/components/common/HeaderBar.css"]["iconWrapper"]; 117 + export const scrollable: MappedModules["discord/components/common/HeaderBar.css"]["scrollable"]; 118 + export const selected: MappedModules["discord/components/common/HeaderBar.css"]["selected"]; 119 + export const themed: MappedModules["discord/components/common/HeaderBar.css"]["themed"]; 120 + export const themedMobile: MappedModules["discord/components/common/HeaderBar.css"]["themedMobile"]; 121 + export const title: MappedModules["discord/components/common/HeaderBar.css"]["title"]; 122 + export const titleWrapper: MappedModules["discord/components/common/HeaderBar.css"]["titleWrapper"]; 123 + export const toolbar: MappedModules["discord/components/common/HeaderBar.css"]["toolbar"]; 124 + export const transparent: MappedModules["discord/components/common/HeaderBar.css"]["transparent"]; 125 + export const upperContainer: MappedModules["discord/components/common/HeaderBar.css"]["upperContainer"]; 126 + } 127 + 128 + declare module "@moonlight-mod/wp/discord/components/common/HelpMessage.css" { 129 + import { MappedModules } from "@moonlight-mod/mappings"; 130 + export const container: MappedModules["discord/components/common/HelpMessage.css"]["container"]; 131 + export const icon: MappedModules["discord/components/common/HelpMessage.css"]["icon"]; 132 + export const iconDiv: MappedModules["discord/components/common/HelpMessage.css"]["iconDiv"]; 133 + export const text: MappedModules["discord/components/common/HelpMessage.css"]["text"]; 134 + export const positive: MappedModules["discord/components/common/HelpMessage.css"]["positive"]; 135 + export const warning: MappedModules["discord/components/common/HelpMessage.css"]["warning"]; 136 + export const info: MappedModules["discord/components/common/HelpMessage.css"]["info"]; 137 + export const error: MappedModules["discord/components/common/HelpMessage.css"]["error"]; 138 + } 139 + 140 + declare module "@moonlight-mod/wp/discord/components/common/Image" {} 141 + 142 + declare module "@moonlight-mod/wp/discord/components/common/PanelButton" { 143 + import { MappedModules } from "@moonlight-mod/mappings"; 144 + const _default: MappedModules["discord/components/common/PanelButton"]["default"]; 145 + export default _default; 146 + } 147 + 148 + declare module "@moonlight-mod/wp/discord/components/common/Scroller.css" { 149 + import { MappedModules } from "@moonlight-mod/mappings"; 150 + export const auto: MappedModules["discord/components/common/Scroller.css"]["auto"]; 151 + export const content: MappedModules["discord/components/common/Scroller.css"]["content"]; 152 + export const customTheme: MappedModules["discord/components/common/Scroller.css"]["customTheme"]; 153 + export const disableScrollAnchor: MappedModules["discord/components/common/Scroller.css"]["disableScrollAnchor"]; 154 + export const fade: MappedModules["discord/components/common/Scroller.css"]["fade"]; 155 + export const managedReactiveScroller: MappedModules["discord/components/common/Scroller.css"]["managedReactiveScroller"]; 156 + export const none: MappedModules["discord/components/common/Scroller.css"]["none"]; 157 + export const pointerCover: MappedModules["discord/components/common/Scroller.css"]["pointerCover"]; 158 + export const scrolling: MappedModules["discord/components/common/Scroller.css"]["scrolling"]; 159 + export const thin: MappedModules["discord/components/common/Scroller.css"]["thin"]; 160 } 161 162 declare module "@moonlight-mod/wp/discord/components/common/index" { 163 import { MappedModules } from "@moonlight-mod/mappings"; 164 + export const Clickable: MappedModules["discord/components/common/index"]["Clickable"]; 165 + export const TextInput: MappedModules["discord/components/common/index"]["TextInput"]; 166 + export const TextArea: MappedModules["discord/components/common/index"]["TextArea"]; 167 + export const FormDivider: MappedModules["discord/components/common/index"]["FormDivider"]; 168 + export const FormSection: MappedModules["discord/components/common/index"]["FormSection"]; 169 + export const FormText: MappedModules["discord/components/common/index"]["FormText"]; 170 + export const FormTitle: MappedModules["discord/components/common/index"]["FormTitle"]; 171 + export const FormSwitch: MappedModules["discord/components/common/index"]["FormSwitch"]; 172 + export const FormItem: MappedModules["discord/components/common/index"]["FormItem"]; 173 + export const Slider: MappedModules["discord/components/common/index"]["Slider"]; 174 + export const Switch: MappedModules["discord/components/common/index"]["Switch"]; 175 + export const Button: MappedModules["discord/components/common/index"]["Button"]; 176 + export const Tooltip: MappedModules["discord/components/common/index"]["Tooltip"]; 177 + export const Avatar: MappedModules["discord/components/common/index"]["Avatar"]; 178 + export const AvatarSizes: MappedModules["discord/components/common/index"]["AvatarSizes"]; 179 + export const AvatarSizeSpecs: MappedModules["discord/components/common/index"]["AvatarSizeSpecs"]; 180 + export const Scroller: MappedModules["discord/components/common/index"]["Scroller"]; 181 + export const Text: MappedModules["discord/components/common/index"]["Text"]; 182 + export const Heading: MappedModules["discord/components/common/index"]["Heading"]; 183 + export const Card: MappedModules["discord/components/common/index"]["Card"]; 184 + export const Popout: MappedModules["discord/components/common/index"]["Popout"]; 185 + export const Dialog: MappedModules["discord/components/common/index"]["Dialog"]; 186 + export const Menu: MappedModules["discord/components/common/index"]["Menu"]; 187 + export const TabBar: MappedModules["discord/components/common/index"]["TabBar"]; 188 + export const SingleSelect: MappedModules["discord/components/common/index"]["SingleSelect"]; 189 + export const Select: MappedModules["discord/components/common/index"]["Select"]; 190 + export const NoticeColors: MappedModules["discord/components/common/index"]["NoticeColors"]; 191 + export const Notice: MappedModules["discord/components/common/index"]["Notice"]; 192 + export const NoticeCloseButton: MappedModules["discord/components/common/index"]["NoticeCloseButton"]; 193 + export const PrimaryCTANoticeButton: MappedModules["discord/components/common/index"]["PrimaryCTANoticeButton"]; 194 + export const Breadcrumbs: MappedModules["discord/components/common/index"]["Breadcrumbs"]; 195 + export const Image: MappedModules["discord/components/common/index"]["Image"]; 196 + export const tokens: MappedModules["discord/components/common/index"]["tokens"]; 197 + export const useVariableSelect: MappedModules["discord/components/common/index"]["useVariableSelect"]; 198 + export const useMultiSelect: MappedModules["discord/components/common/index"]["useMultiSelect"]; 199 + export const multiSelect: MappedModules["discord/components/common/index"]["multiSelect"]; 200 + export const openModal: MappedModules["discord/components/common/index"]["openModal"]; 201 + export const openModalLazy: MappedModules["discord/components/common/index"]["openModalLazy"]; 202 + export const closeModal: MappedModules["discord/components/common/index"]["closeModal"]; 203 + export const AngleBracketsIcon: MappedModules["discord/components/common/index"]["AngleBracketsIcon"]; 204 + export const ArrowAngleLeftUpIcon: MappedModules["discord/components/common/index"]["ArrowAngleLeftUpIcon"]; 205 + export const ArrowAngleRightUpIcon: MappedModules["discord/components/common/index"]["ArrowAngleRightUpIcon"]; 206 + export const ArrowsUpDownIcon: MappedModules["discord/components/common/index"]["ArrowsUpDownIcon"]; 207 + export const BookCheckIcon: MappedModules["discord/components/common/index"]["BookCheckIcon"]; 208 + export const ChannelListIcon: MappedModules["discord/components/common/index"]["ChannelListIcon"]; 209 + export const ChevronSmallDownIcon: MappedModules["discord/components/common/index"]["ChevronSmallDownIcon"]; 210 + export const ChevronSmallUpIcon: MappedModules["discord/components/common/index"]["ChevronSmallUpIcon"]; 211 + export const CircleInformationIcon: MappedModules["discord/components/common/index"]["CircleInformationIcon"]; 212 + export const CircleWarningIcon: MappedModules["discord/components/common/index"]["CircleWarningIcon"]; 213 + export const CircleXIcon: MappedModules["discord/components/common/index"]["CircleXIcon"]; 214 + export const ClydeIcon: MappedModules["discord/components/common/index"]["ClydeIcon"]; 215 + export const CopyIcon: MappedModules["discord/components/common/index"]["CopyIcon"]; 216 + export const DownloadIcon: MappedModules["discord/components/common/index"]["DownloadIcon"]; 217 + export const FullscreenEnterIcon: MappedModules["discord/components/common/index"]["FullscreenEnterIcon"]; 218 + export const GameControllerIcon: MappedModules["discord/components/common/index"]["GameControllerIcon"]; 219 + export const GlobeEarthIcon: MappedModules["discord/components/common/index"]["GlobeEarthIcon"]; 220 + export const HeartIcon: MappedModules["discord/components/common/index"]["HeartIcon"]; 221 + export const LinkIcon: MappedModules["discord/components/common/index"]["LinkIcon"]; 222 + export const MaximizeIcon: MappedModules["discord/components/common/index"]["MaximizeIcon"]; 223 + export const MinusIcon: MappedModules["discord/components/common/index"]["MinusIcon"]; 224 + export const MobilePhoneIcon: MappedModules["discord/components/common/index"]["MobilePhoneIcon"]; 225 + export const PauseIcon: MappedModules["discord/components/common/index"]["PauseIcon"]; 226 + export const PlayIcon: MappedModules["discord/components/common/index"]["PlayIcon"]; 227 + export const PlusLargeIcon: MappedModules["discord/components/common/index"]["PlusLargeIcon"]; 228 + export const RetryIcon: MappedModules["discord/components/common/index"]["RetryIcon"]; 229 + export const ScienceIcon: MappedModules["discord/components/common/index"]["ScienceIcon"]; 230 + export const ScreenIcon: MappedModules["discord/components/common/index"]["ScreenIcon"]; 231 + export const StarIcon: MappedModules["discord/components/common/index"]["StarIcon"]; 232 + export const TrashIcon: MappedModules["discord/components/common/index"]["TrashIcon"]; 233 + export const WarningIcon: MappedModules["discord/components/common/index"]["WarningIcon"]; 234 + export const WindowLaunchIcon: MappedModules["discord/components/common/index"]["WindowLaunchIcon"]; 235 + export const WindowTopOutlineIcon: MappedModules["discord/components/common/index"]["WindowTopOutlineIcon"]; 236 + export const XLargeIcon: MappedModules["discord/components/common/index"]["XLargeIcon"]; 237 + export const XSmallIcon: MappedModules["discord/components/common/index"]["XSmallIcon"]; 238 + export const ConfirmModal: MappedModules["discord/components/common/index"]["ConfirmModal"]; 239 + export const H: MappedModules["discord/components/common/index"]["H"]; 240 + export const HelpMessage: MappedModules["discord/components/common/index"]["HelpMessage"]; 241 + export const ModalCloseButton: MappedModules["discord/components/common/index"]["ModalCloseButton"]; 242 + export const ModalContent: MappedModules["discord/components/common/index"]["ModalContent"]; 243 + export const ModalFooter: MappedModules["discord/components/common/index"]["ModalFooter"]; 244 + export const ModalHeader: MappedModules["discord/components/common/index"]["ModalHeader"]; 245 + export const ModalRoot: MappedModules["discord/components/common/index"]["ModalRoot"]; 246 + export const NumberInputStepper: MappedModules["discord/components/common/index"]["NumberInputStepper"]; 247 + export const SearchableSelect: MappedModules["discord/components/common/index"]["SearchableSelect"]; 248 + export const createToast: MappedModules["discord/components/common/index"]["createToast"]; 249 + export const popToast: MappedModules["discord/components/common/index"]["popToast"]; 250 + export const showToast: MappedModules["discord/components/common/index"]["showToast"]; 251 + export const useThemeContext: MappedModules["discord/components/common/index"]["useThemeContext"]; 252 + export const AccessibilityAnnouncer: MappedModules["discord/components/common/index"]["AccessibilityAnnouncer"]; 253 + export const BackdropStyles: MappedModules["discord/components/common/index"]["BackdropStyles"]; 254 + export const BadgeShapes: MappedModules["discord/components/common/index"]["BadgeShapes"]; 255 + export const CardTypes: MappedModules["discord/components/common/index"]["CardTypes"]; 256 + export const CircleIconButtonColors: MappedModules["discord/components/common/index"]["CircleIconButtonColors"]; 257 + export const CircleIconButtonSizes: MappedModules["discord/components/common/index"]["CircleIconButtonSizes"]; 258 + export const FormErrorBlockColors: MappedModules["discord/components/common/index"]["FormErrorBlockColors"]; 259 + export const FormNoticeImagePositions: MappedModules["discord/components/common/index"]["FormNoticeImagePositions"]; 260 + export const FormTitleTags: MappedModules["discord/components/common/index"]["FormTitleTags"]; 261 + export const HelpMessageTypes: MappedModules["discord/components/common/index"]["HelpMessageTypes"]; 262 + export const ModalSize: MappedModules["discord/components/common/index"]["ModalSize"]; 263 + export const ModalTransitionState: MappedModules["discord/components/common/index"]["ModalTransitionState"]; 264 + export const PRETTY_KEYS: MappedModules["discord/components/common/index"]["PRETTY_KEYS"]; 265 + export const SelectLooks: MappedModules["discord/components/common/index"]["SelectLooks"]; 266 + export const SpinnerTypes: MappedModules["discord/components/common/index"]["SpinnerTypes"]; 267 + export const StatusTypes: MappedModules["discord/components/common/index"]["StatusTypes"]; 268 + export const ToastPosition: MappedModules["discord/components/common/index"]["ToastPosition"]; 269 + export const ToastType: MappedModules["discord/components/common/index"]["ToastType"]; 270 + export const TransitionStates: MappedModules["discord/components/common/index"]["TransitionStates"]; 271 + export const DEFAULT_MODAL_CONTEXT: MappedModules["discord/components/common/index"]["DEFAULT_MODAL_CONTEXT"]; 272 + export const LOW_SATURATION_THRESHOLD: MappedModules["discord/components/common/index"]["LOW_SATURATION_THRESHOLD"]; 273 + export const LayerClassName: MappedModules["discord/components/common/index"]["LayerClassName"]; 274 + export const POPOUT_MODAL_CONTEXT: MappedModules["discord/components/common/index"]["POPOUT_MODAL_CONTEXT"]; 275 } 276 277 + declare module "@moonlight-mod/wp/discord/components/modals/ConfirmModal" { 278 import { MappedModules } from "@moonlight-mod/mappings"; 279 + const _default: MappedModules["discord/components/modals/ConfirmModal"]["default"]; 280 + export default _default; 281 + } 282 + 283 + declare module "@moonlight-mod/wp/discord/lib/BaseRecord" { 284 + import { MappedModules } from "@moonlight-mod/mappings"; 285 + const _default: MappedModules["discord/lib/BaseRecord"]["default"]; 286 + export default _default; 287 + } 288 + 289 + declare module "@moonlight-mod/wp/discord/lib/web/Storage" { 290 + import { MappedModules } from "@moonlight-mod/mappings"; 291 + export const ObjectStorage: MappedModules["discord/lib/web/Storage"]["ObjectStorage"]; 292 + export const impl: MappedModules["discord/lib/web/Storage"]["impl"]; 293 + } 294 + 295 + declare module "@moonlight-mod/wp/discord/modules/build_overrides/web/BuildOverride.css" { 296 + import { MappedModules } from "@moonlight-mod/mappings"; 297 + export const wrapper: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["wrapper"]; 298 + export const titleRegion: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["titleRegion"]; 299 + export const title: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["title"]; 300 + export const infoIcon: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["infoIcon"]; 301 + export const copyLink: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["copyLink"]; 302 + export const copied: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["copied"]; 303 + export const copyLinkIcon: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["copyLinkIcon"]; 304 + export const content: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["content"]; 305 + export const infoLink: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["infoLink"]; 306 + export const buildInfo: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["buildInfo"]; 307 + export const button: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["button"]; 308 + export const buttonSize: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["buttonSize"]; 309 + export const subHead: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["subHead"]; 310 + export const icon: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["icon"]; 311 + export const buildDetails: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["buildDetails"]; 312 + export const barLoader: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["barLoader"]; 313 + export const barTitle: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["barTitle"]; 314 + export const buttonLoader: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["buttonLoader"]; 315 + export const disabledButtonOverride: MappedModules["discord/modules/build_overrides/web/BuildOverride.css"]["disabledButtonOverride"]; 316 + } 317 + 318 + declare module "@moonlight-mod/wp/discord/modules/discovery/web/Discovery.css" { 319 + import { MappedModules } from "@moonlight-mod/mappings"; 320 + export const header: MappedModules["discord/modules/discovery/web/Discovery.css"]["header"]; 321 + export const headerImage: MappedModules["discord/modules/discovery/web/Discovery.css"]["headerImage"]; 322 + export const headerImageSimple: MappedModules["discord/modules/discovery/web/Discovery.css"]["headerImageSimple"]; 323 + export const headerImageBG: MappedModules["discord/modules/discovery/web/Discovery.css"]["headerImageBG"]; 324 + export const searchTitle: MappedModules["discord/modules/discovery/web/Discovery.css"]["searchTitle"]; 325 + export const searchSubtitle: MappedModules["discord/modules/discovery/web/Discovery.css"]["searchSubtitle"]; 326 + export const headerContentWrapper: MappedModules["discord/modules/discovery/web/Discovery.css"]["headerContentWrapper"]; 327 + export const headerContent: MappedModules["discord/modules/discovery/web/Discovery.css"]["headerContent"]; 328 + export const headerContentSmall: MappedModules["discord/modules/discovery/web/Discovery.css"]["headerContentSmall"]; 329 + export const searchBox: MappedModules["discord/modules/discovery/web/Discovery.css"]["searchBox"]; 330 + export const searchBoxInput: MappedModules["discord/modules/discovery/web/Discovery.css"]["searchBoxInput"]; 331 + export const closeIcon: MappedModules["discord/modules/discovery/web/Discovery.css"]["closeIcon"]; 332 + export const searchIcon: MappedModules["discord/modules/discovery/web/Discovery.css"]["searchIcon"]; 333 + export const tabBar: MappedModules["discord/modules/discovery/web/Discovery.css"]["tabBar"]; 334 + export const tabBarItem: MappedModules["discord/modules/discovery/web/Discovery.css"]["tabBarItem"]; 335 + export const sectionHeader: MappedModules["discord/modules/discovery/web/Discovery.css"]["sectionHeader"]; 336 + } 337 + 338 + declare module "@moonlight-mod/wp/discord/modules/forums/web/Forums.css" { 339 + import { MappedModules } from "@moonlight-mod/mappings"; 340 + export const container: MappedModules["discord/modules/forums/web/Forums.css"]["container"]; 341 + export const uploadArea: MappedModules["discord/modules/forums/web/Forums.css"]["uploadArea"]; 342 + export const label: MappedModules["discord/modules/forums/web/Forums.css"]["label"]; 343 + export const content: MappedModules["discord/modules/forums/web/Forums.css"]["content"]; 344 + export const noListContainer: MappedModules["discord/modules/forums/web/Forums.css"]["noListContainer"]; 345 + export const list: MappedModules["discord/modules/forums/web/Forums.css"]["list"]; 346 + export const grid: MappedModules["discord/modules/forums/web/Forums.css"]["grid"]; 347 + export const headerRow: MappedModules["discord/modules/forums/web/Forums.css"]["headerRow"]; 348 + export const card: MappedModules["discord/modules/forums/web/Forums.css"]["card"]; 349 + export const columnsSpan: MappedModules["discord/modules/forums/web/Forums.css"]["columnsSpan"]; 350 + export const emptyStateRow: MappedModules["discord/modules/forums/web/Forums.css"]["emptyStateRow"]; 351 + export const newMemberBanner: MappedModules["discord/modules/forums/web/Forums.css"]["newMemberBanner"]; 352 + export const gridViewBanner: MappedModules["discord/modules/forums/web/Forums.css"]["gridViewBanner"]; 353 + export const placeholder: MappedModules["discord/modules/forums/web/Forums.css"]["placeholder"]; 354 + export const mainCard: MappedModules["discord/modules/forums/web/Forums.css"]["mainCard"]; 355 + export const emptyMainCard: MappedModules["discord/modules/forums/web/Forums.css"]["emptyMainCard"]; 356 + export const outOfDate: MappedModules["discord/modules/forums/web/Forums.css"]["outOfDate"]; 357 + export const header: MappedModules["discord/modules/forums/web/Forums.css"]["header"]; 358 + export const matchingPostsRow: MappedModules["discord/modules/forums/web/Forums.css"]["matchingPostsRow"]; 359 + export const headerWithMatchingPosts: MappedModules["discord/modules/forums/web/Forums.css"]["headerWithMatchingPosts"]; 360 + export const noForm: MappedModules["discord/modules/forums/web/Forums.css"]["noForm"]; 361 + export const sortContainer: MappedModules["discord/modules/forums/web/Forums.css"]["sortContainer"]; 362 + export const sort: MappedModules["discord/modules/forums/web/Forums.css"]["sort"]; 363 + export const sortPopout: MappedModules["discord/modules/forums/web/Forums.css"]["sortPopout"]; 364 + export const archivedDividerRow: MappedModules["discord/modules/forums/web/Forums.css"]["archivedDividerRow"]; 365 + export const archivedDivider: MappedModules["discord/modules/forums/web/Forums.css"]["archivedDivider"]; 366 + export const newPostsButton: MappedModules["discord/modules/forums/web/Forums.css"]["newPostsButton"]; 367 + export const loadingCard: MappedModules["discord/modules/forums/web/Forums.css"]["loadingCard"]; 368 + export const enterIcon: MappedModules["discord/modules/forums/web/Forums.css"]["enterIcon"]; 369 + export const warnIcon: MappedModules["discord/modules/forums/web/Forums.css"]["warnIcon"]; 370 + export const searchIcon: MappedModules["discord/modules/forums/web/Forums.css"]["searchIcon"]; 371 + export const missingReadHistoryPermission: MappedModules["discord/modules/forums/web/Forums.css"]["missingReadHistoryPermission"]; 372 + export const divider: MappedModules["discord/modules/forums/web/Forums.css"]["divider"]; 373 + export const tagsContainer: MappedModules["discord/modules/forums/web/Forums.css"]["tagsContainer"]; 374 + export const filterIcon: MappedModules["discord/modules/forums/web/Forums.css"]["filterIcon"]; 375 + export const tagList: MappedModules["discord/modules/forums/web/Forums.css"]["tagList"]; 376 + export const tagListInner: MappedModules["discord/modules/forums/web/Forums.css"]["tagListInner"]; 377 + export const tag: MappedModules["discord/modules/forums/web/Forums.css"]["tag"]; 378 + export const tagsButton: MappedModules["discord/modules/forums/web/Forums.css"]["tagsButton"]; 379 + export const tagsButtonInner: MappedModules["discord/modules/forums/web/Forums.css"]["tagsButtonInner"]; 380 + export const tagsButtonPlaceholder: MappedModules["discord/modules/forums/web/Forums.css"]["tagsButtonPlaceholder"]; 381 + export const tagsButtonWithCount: MappedModules["discord/modules/forums/web/Forums.css"]["tagsButtonWithCount"]; 382 + export const sortDropdown: MappedModules["discord/modules/forums/web/Forums.css"]["sortDropdown"]; 383 + export const sortDropdownInner: MappedModules["discord/modules/forums/web/Forums.css"]["sortDropdownInner"]; 384 + export const sortDropdownText: MappedModules["discord/modules/forums/web/Forums.css"]["sortDropdownText"]; 385 + export const clear: MappedModules["discord/modules/forums/web/Forums.css"]["clear"]; 386 + export const matchingPosts: MappedModules["discord/modules/forums/web/Forums.css"]["matchingPosts"]; 387 + export const startPostHelp: MappedModules["discord/modules/forums/web/Forums.css"]["startPostHelp"]; 388 + export const tagsSpacer: MappedModules["discord/modules/forums/web/Forums.css"]["tagsSpacer"]; 389 + export const keyboardShortcut: MappedModules["discord/modules/forums/web/Forums.css"]["keyboardShortcut"]; 390 + export const key: MappedModules["discord/modules/forums/web/Forums.css"]["key"]; 391 + export const countContainer: MappedModules["discord/modules/forums/web/Forums.css"]["countContainer"]; 392 + export const countText: MappedModules["discord/modules/forums/web/Forums.css"]["countText"]; 393 + export const optInNotice: MappedModules["discord/modules/forums/web/Forums.css"]["optInNotice"]; 394 + } 395 + 396 + declare module "@moonlight-mod/wp/discord/modules/forums/web/Header.css" { 397 + import { MappedModules } from "@moonlight-mod/mappings"; 398 + export const container: MappedModules["discord/modules/forums/web/Header.css"]["container"]; 399 + export const header: MappedModules["discord/modules/forums/web/Header.css"]["header"]; 400 + export const headerLeft: MappedModules["discord/modules/forums/web/Header.css"]["headerLeft"]; 401 + export const headerText: MappedModules["discord/modules/forums/web/Header.css"]["headerText"]; 402 + export const countContainer: MappedModules["discord/modules/forums/web/Header.css"]["countContainer"]; 403 + export const countText: MappedModules["discord/modules/forums/web/Header.css"]["countText"]; 404 + export const tagContainer: MappedModules["discord/modules/forums/web/Header.css"]["tagContainer"]; 405 + export const tag: MappedModules["discord/modules/forums/web/Header.css"]["tag"]; 406 + export const clear: MappedModules["discord/modules/forums/web/Header.css"]["clear"]; 407 + export const row: MappedModules["discord/modules/forums/web/Header.css"]["row"]; 408 + export const separator: MappedModules["discord/modules/forums/web/Header.css"]["separator"]; 409 + } 410 + 411 + declare module "@moonlight-mod/wp/discord/modules/forums/web/SortMenu.css" { 412 + import { MappedModules } from "@moonlight-mod/mappings"; 413 + export const container: MappedModules["discord/modules/forums/web/SortMenu.css"]["container"]; 414 + export const clearText: MappedModules["discord/modules/forums/web/SortMenu.css"]["clearText"]; 415 + } 416 + 417 + declare module "@moonlight-mod/wp/discord/modules/forums/web/Tag" { 418 + import { MappedModules } from "@moonlight-mod/mappings"; 419 + const _default: MappedModules["discord/modules/forums/web/Tag"]["default"]; 420 + export default _default; 421 + export const TagBar: MappedModules["discord/modules/forums/web/Tag"]["TagBar"]; 422 + } 423 + 424 + declare module "@moonlight-mod/wp/discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css" { 425 + import { MappedModules } from "@moonlight-mod/mappings"; 426 + export const addButton: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["addButton"]; 427 + export const container: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["container"]; 428 + export const emptyRowContainer: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["emptyRowContainer"]; 429 + export const emptyRowText: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["emptyRowText"]; 430 + export const headerContainer: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["headerContainer"]; 431 + export const list: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["list"]; 432 + export const memberDetails: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["memberDetails"]; 433 + export const memberRow: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["memberRow"]; 434 + export const removeButton: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["removeButton"]; 435 + export const removeButtonContainer: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["removeButtonContainer"]; 436 + export const removeButtonDisabled: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["removeButtonDisabled"]; 437 + export const removeTip: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["removeTip"]; 438 + export const searchContainer: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["searchContainer"]; 439 + export const searchWarning: MappedModules["discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css"]["searchWarning"]; 440 + } 441 + 442 + declare module "@moonlight-mod/wp/discord/modules/guild_settings/web/AppCard.css" { 443 + import { MappedModules } from "@moonlight-mod/mappings"; 444 + export const card: MappedModules["discord/modules/guild_settings/web/AppCard.css"]["card"]; 445 + export const inModal: MappedModules["discord/modules/guild_settings/web/AppCard.css"]["inModal"]; 446 + export const cardHeader: MappedModules["discord/modules/guild_settings/web/AppCard.css"]["cardHeader"]; 447 + export const title: MappedModules["discord/modules/guild_settings/web/AppCard.css"]["title"]; 448 + } 449 + 450 + declare module "@moonlight-mod/wp/discord/modules/guild_settings/web/AppCardItem.css" { 451 + import { MappedModules } from "@moonlight-mod/mappings"; 452 + export const icon: MappedModules["discord/modules/guild_settings/web/AppCardItem.css"]["icon"]; 453 + export const identifier: MappedModules["discord/modules/guild_settings/web/AppCardItem.css"]["identifier"]; 454 + export const item: MappedModules["discord/modules/guild_settings/web/AppCardItem.css"]["item"]; 455 + export const statusContainer: MappedModules["discord/modules/guild_settings/web/AppCardItem.css"]["statusContainer"]; 456 + export const statusLine: MappedModules["discord/modules/guild_settings/web/AppCardItem.css"]["statusLine"]; 457 + export const statusIcon: MappedModules["discord/modules/guild_settings/web/AppCardItem.css"]["statusIcon"]; 458 + } 459 + 460 + declare module "@moonlight-mod/wp/discord/modules/guild_settings/web/SearchSection.css" { 461 + import { MappedModules } from "@moonlight-mod/mappings"; 462 + export const container: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["container"]; 463 + export const headerContainer: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["headerContainer"]; 464 + export const searchContainer: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["searchContainer"]; 465 + export const searchWarning: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["searchWarning"]; 466 + export const addButton: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["addButton"]; 467 + export const memberRow: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["memberRow"]; 468 + export const emptyRowContainer: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["emptyRowContainer"]; 469 + export const emptyRowText: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["emptyRowText"]; 470 + export const memberDetails: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["memberDetails"]; 471 + export const list: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["list"]; 472 + export const removeButtonContainer: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["removeButtonContainer"]; 473 + export const removeButton: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["removeButton"]; 474 + export const removeButtonDisabled: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["removeButtonDisabled"]; 475 + export const removeTip: MappedModules["discord/modules/guild_settings/web/SearchSection.css"]["removeTip"]; 476 + } 477 + 478 + declare module "@moonlight-mod/wp/discord/modules/guild_sidebar/web/CategoryChannel.css" { 479 + import { MappedModules } from "@moonlight-mod/mappings"; 480 + export const containerDefault: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["containerDefault"]; 481 + export const containerDragBefore: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["containerDragBefore"]; 482 + export const containerDragAfter: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["containerDragAfter"]; 483 + export const addButton: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["addButton"]; 484 + export const forceVisible: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["forceVisible"]; 485 + export const iconVisibility: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["iconVisibility"]; 486 + export const addButtonIcon: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["addButtonIcon"]; 487 + export const wrapper: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["wrapper"]; 488 + export const wrapperStatic: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["wrapperStatic"]; 489 + export const clickable: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["clickable"]; 490 + export const children: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["children"]; 491 + export const mainContent: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["mainContent"]; 492 + export const icon: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["icon"]; 493 + export const collapsed: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["collapsed"]; 494 + export const muted: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["muted"]; 495 + export const name: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["name"]; 496 + export const dismissWrapper: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["dismissWrapper"]; 497 + export const dismissButton: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["dismissButton"]; 498 + export const dismiss: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["dismiss"]; 499 + export const voiceChannelsButton: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["voiceChannelsButton"]; 500 + export const voiceChannelsToggleIcon: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["voiceChannelsToggleIcon"]; 501 + export const refreshVoiceChannelsButton: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["refreshVoiceChannelsButton"]; 502 + export const refreshVoiceChannelsButtonInner: MappedModules["discord/modules/guild_sidebar/web/CategoryChannel.css"]["refreshVoiceChannelsButtonInner"]; 503 } 504 505 declare module "@moonlight-mod/wp/discord/modules/markup/MarkupUtils" { 506 import { MappedModules } from "@moonlight-mod/mappings"; 507 + const _default: MappedModules["discord/modules/markup/MarkupUtils"]["default"]; 508 + export default _default; 509 + } 510 + 511 + declare module "@moonlight-mod/wp/discord/modules/menus/web/Menu" { 512 + import { MappedModules } from "@moonlight-mod/mappings"; 513 + export const MenuSpinner: MappedModules["discord/modules/menus/web/Menu"]["MenuSpinner"]; 514 + export const Menu: MappedModules["discord/modules/menus/web/Menu"]["Menu"]; 515 + } 516 + 517 + declare module "@moonlight-mod/wp/discord/modules/messages/web/Markup.css" { 518 + import { MappedModules } from "@moonlight-mod/mappings"; 519 + export const markup: MappedModules["discord/modules/messages/web/Markup.css"]["markup"]; 520 + export const inlineFormat: MappedModules["discord/modules/messages/web/Markup.css"]["inlineFormat"]; 521 + export const codeContainer: MappedModules["discord/modules/messages/web/Markup.css"]["codeContainer"]; 522 + export const codeActions: MappedModules["discord/modules/messages/web/Markup.css"]["codeActions"]; 523 + export const blockquoteContainer: MappedModules["discord/modules/messages/web/Markup.css"]["blockquoteContainer"]; 524 + export const blockquoteDivider: MappedModules["discord/modules/messages/web/Markup.css"]["blockquoteDivider"]; 525 + export const slateBlockquoteContainer: MappedModules["discord/modules/messages/web/Markup.css"]["slateBlockquoteContainer"]; 526 + export const roleMention: MappedModules["discord/modules/messages/web/Markup.css"]["roleMention"]; 527 + export const rolePopout: MappedModules["discord/modules/messages/web/Markup.css"]["rolePopout"]; 528 + export const roleHeader: MappedModules["discord/modules/messages/web/Markup.css"]["roleHeader"]; 529 + export const roleScroller: MappedModules["discord/modules/messages/web/Markup.css"]["roleScroller"]; 530 + export const timestamp: MappedModules["discord/modules/messages/web/Markup.css"]["timestamp"]; 531 + export const timestampTooltip: MappedModules["discord/modules/messages/web/Markup.css"]["timestampTooltip"]; 532 + } 533 + 534 + declare module "@moonlight-mod/wp/discord/modules/messages/web/Message.css" { 535 + import { MappedModules } from "@moonlight-mod/mappings"; 536 + export const wrapper: MappedModules["discord/modules/messages/web/Message.css"]["wrapper"]; 537 + export const compact: MappedModules["discord/modules/messages/web/Message.css"]["compact"]; 538 + export const cozy: MappedModules["discord/modules/messages/web/Message.css"]["cozy"]; 539 + export const contentOnly: MappedModules["discord/modules/messages/web/Message.css"]["contentOnly"]; 540 + export const repliedMessage: MappedModules["discord/modules/messages/web/Message.css"]["repliedMessage"]; 541 + export const threadMessageAccessory: MappedModules["discord/modules/messages/web/Message.css"]["threadMessageAccessory"]; 542 + export const executedCommand: MappedModules["discord/modules/messages/web/Message.css"]["executedCommand"]; 543 + export const latin12CompactTimeStamp: MappedModules["discord/modules/messages/web/Message.css"]["latin12CompactTimeStamp"]; 544 + export const latin24CompactTimeStamp: MappedModules["discord/modules/messages/web/Message.css"]["latin24CompactTimeStamp"]; 545 + export const asianCompactTimeStamp: MappedModules["discord/modules/messages/web/Message.css"]["asianCompactTimeStamp"]; 546 + export const contextCommandMessage: MappedModules["discord/modules/messages/web/Message.css"]["contextCommandMessage"]; 547 + export const messageSpine: MappedModules["discord/modules/messages/web/Message.css"]["messageSpine"]; 548 + export const repliedMessageClickableSpine: MappedModules["discord/modules/messages/web/Message.css"]["repliedMessageClickableSpine"]; 549 + export const repliedMessageContentHovered: MappedModules["discord/modules/messages/web/Message.css"]["repliedMessageContentHovered"]; 550 + export const threadMessageAccessoryAvatar: MappedModules["discord/modules/messages/web/Message.css"]["threadMessageAccessoryAvatar"]; 551 + export const replyAvatar: MappedModules["discord/modules/messages/web/Message.css"]["replyAvatar"]; 552 + export const replyBadge: MappedModules["discord/modules/messages/web/Message.css"]["replyBadge"]; 553 + export const executedCommandAvatar: MappedModules["discord/modules/messages/web/Message.css"]["executedCommandAvatar"]; 554 + export const replyChatIconContainer: MappedModules["discord/modules/messages/web/Message.css"]["replyChatIconContainer"]; 555 + export const replyIcon: MappedModules["discord/modules/messages/web/Message.css"]["replyIcon"]; 556 + export const clanTagChiplet: MappedModules["discord/modules/messages/web/Message.css"]["clanTagChiplet"]; 557 + export const userJoinSystemMessageIcon: MappedModules["discord/modules/messages/web/Message.css"]["userJoinSystemMessageIcon"]; 558 + export const ticketIcon: MappedModules["discord/modules/messages/web/Message.css"]["ticketIcon"]; 559 + export const commandIcon: MappedModules["discord/modules/messages/web/Message.css"]["commandIcon"]; 560 + export const username: MappedModules["discord/modules/messages/web/Message.css"]["username"]; 561 + export const roleDot: MappedModules["discord/modules/messages/web/Message.css"]["roleDot"]; 562 + export const commandName: MappedModules["discord/modules/messages/web/Message.css"]["commandName"]; 563 + export const appsIcon: MappedModules["discord/modules/messages/web/Message.css"]["appsIcon"]; 564 + export const appLauncherOnboardingCommandName: MappedModules["discord/modules/messages/web/Message.css"]["appLauncherOnboardingCommandName"]; 565 + export const targetUsername: MappedModules["discord/modules/messages/web/Message.css"]["targetUsername"]; 566 + export const executedCommandSeparator: MappedModules["discord/modules/messages/web/Message.css"]["executedCommandSeparator"]; 567 + export const repliedTextPreview: MappedModules["discord/modules/messages/web/Message.css"]["repliedTextPreview"]; 568 + export const threadMessageAccessoryPreview: MappedModules["discord/modules/messages/web/Message.css"]["threadMessageAccessoryPreview"]; 569 + export const repliedTextContent: MappedModules["discord/modules/messages/web/Message.css"]["repliedTextContent"]; 570 + export const clickable: MappedModules["discord/modules/messages/web/Message.css"]["clickable"]; 571 + export const repliedMessageClickableSpineHovered: MappedModules["discord/modules/messages/web/Message.css"]["repliedMessageClickableSpineHovered"]; 572 + export const threadMessageAccessoryContent: MappedModules["discord/modules/messages/web/Message.css"]["threadMessageAccessoryContent"]; 573 + export const repliedTextPlaceholder: MappedModules["discord/modules/messages/web/Message.css"]["repliedTextPlaceholder"]; 574 + export const threadMessageAccessoryPlaceholder: MappedModules["discord/modules/messages/web/Message.css"]["threadMessageAccessoryPlaceholder"]; 575 + export const repliedTextContentTrailingIcon: MappedModules["discord/modules/messages/web/Message.css"]["repliedTextContentTrailingIcon"]; 576 + export const threadMessageAccessoryContentTrailingIcon: MappedModules["discord/modules/messages/web/Message.css"]["threadMessageAccessoryContentTrailingIcon"]; 577 + export const repliedTextContentLeadingIcon: MappedModules["discord/modules/messages/web/Message.css"]["repliedTextContentLeadingIcon"]; 578 + export const threadMessageAccessoryContentLeadingIcon: MappedModules["discord/modules/messages/web/Message.css"]["threadMessageAccessoryContentLeadingIcon"]; 579 + export const contents: MappedModules["discord/modules/messages/web/Message.css"]["contents"]; 580 + export const zalgo: MappedModules["discord/modules/messages/web/Message.css"]["zalgo"]; 581 + export const messageContent: MappedModules["discord/modules/messages/web/Message.css"]["messageContent"]; 582 + export const header: MappedModules["discord/modules/messages/web/Message.css"]["header"]; 583 + export const buttonContainer: MappedModules["discord/modules/messages/web/Message.css"]["buttonContainer"]; 584 + export const avatar: MappedModules["discord/modules/messages/web/Message.css"]["avatar"]; 585 + export const avatarDecoration: MappedModules["discord/modules/messages/web/Message.css"]["avatarDecoration"]; 586 + export const roleIcon: MappedModules["discord/modules/messages/web/Message.css"]["roleIcon"]; 587 + export const timestamp: MappedModules["discord/modules/messages/web/Message.css"]["timestamp"]; 588 + export const timestampInline: MappedModules["discord/modules/messages/web/Message.css"]["timestampInline"]; 589 + export const alt: MappedModules["discord/modules/messages/web/Message.css"]["alt"]; 590 + export const timestampTooltip: MappedModules["discord/modules/messages/web/Message.css"]["timestampTooltip"]; 591 + export const timestampVisibleOnHover: MappedModules["discord/modules/messages/web/Message.css"]["timestampVisibleOnHover"]; 592 + export const nitroAuthorBadgeTootip: MappedModules["discord/modules/messages/web/Message.css"]["nitroAuthorBadgeTootip"]; 593 + export const headerText: MappedModules["discord/modules/messages/web/Message.css"]["headerText"]; 594 + export const hasRoleIcon: MappedModules["discord/modules/messages/web/Message.css"]["hasRoleIcon"]; 595 + export const hasBadges: MappedModules["discord/modules/messages/web/Message.css"]["hasBadges"]; 596 + export const botTagCompact: MappedModules["discord/modules/messages/web/Message.css"]["botTagCompact"]; 597 + export const botTagCozy: MappedModules["discord/modules/messages/web/Message.css"]["botTagCozy"]; 598 + export const nitroBadgeSvg: MappedModules["discord/modules/messages/web/Message.css"]["nitroBadgeSvg"]; 599 + export const nitroAuthorBadgeContainer: MappedModules["discord/modules/messages/web/Message.css"]["nitroAuthorBadgeContainer"]; 600 + export const separator: MappedModules["discord/modules/messages/web/Message.css"]["separator"]; 601 + export const hasThread: MappedModules["discord/modules/messages/web/Message.css"]["hasThread"]; 602 + export const isSystemMessage: MappedModules["discord/modules/messages/web/Message.css"]["isSystemMessage"]; 603 + export const hasReply: MappedModules["discord/modules/messages/web/Message.css"]["hasReply"]; 604 + export const markupRtl: MappedModules["discord/modules/messages/web/Message.css"]["markupRtl"]; 605 + export const isSending: MappedModules["discord/modules/messages/web/Message.css"]["isSending"]; 606 + export const isFailed: MappedModules["discord/modules/messages/web/Message.css"]["isFailed"]; 607 + export const isUnsupported: MappedModules["discord/modules/messages/web/Message.css"]["isUnsupported"]; 608 + export const edited: MappedModules["discord/modules/messages/web/Message.css"]["edited"]; 609 + export const communicationDisabled: MappedModules["discord/modules/messages/web/Message.css"]["communicationDisabled"]; 610 + export const compactCommunicationDisabled: MappedModules["discord/modules/messages/web/Message.css"]["compactCommunicationDisabled"]; 611 + export const communicationDisabledOpacity: MappedModules["discord/modules/messages/web/Message.css"]["communicationDisabledOpacity"]; 612 + export const badgesContainer: MappedModules["discord/modules/messages/web/Message.css"]["badgesContainer"]; 613 } 614 615 + declare module "@moonlight-mod/wp/discord/modules/modals/Modals" { 616 import { MappedModules } from "@moonlight-mod/mappings"; 617 + export const closeAllModals: MappedModules["discord/modules/modals/Modals"]["closeAllModals"]; 618 + export const closeAllModalsForContext: MappedModules["discord/modules/modals/Modals"]["closeAllModalsForContext"]; 619 + export const closeModal: MappedModules["discord/modules/modals/Modals"]["closeModal"]; 620 + export const getInteractingModalContext: MappedModules["discord/modules/modals/Modals"]["getInteractingModalContext"]; 621 + export const hasAnyModalOpen: MappedModules["discord/modules/modals/Modals"]["hasAnyModalOpen"]; 622 + export const hasAnyModalOpenSelector: MappedModules["discord/modules/modals/Modals"]["hasAnyModalOpenSelector"]; 623 + export const hasModalOpen: MappedModules["discord/modules/modals/Modals"]["hasModalOpen"]; 624 + export const hasModalOpenSelector: MappedModules["discord/modules/modals/Modals"]["hasModalOpenSelector"]; 625 + export const openModal: MappedModules["discord/modules/modals/Modals"]["openModal"]; 626 + export const openModalLazy: MappedModules["discord/modules/modals/Modals"]["openModalLazy"]; 627 + export const updateModal: MappedModules["discord/modules/modals/Modals"]["updateModal"]; 628 + export const useHasAnyModalOpen: MappedModules["discord/modules/modals/Modals"]["useHasAnyModalOpen"]; 629 + export const useIsModalAtTop: MappedModules["discord/modules/modals/Modals"]["useIsModalAtTop"]; 630 + export const useModalsStore: MappedModules["discord/modules/modals/Modals"]["useModalsStore"]; 631 + } 632 + 633 + declare module "@moonlight-mod/wp/discord/modules/oauth2/index" { 634 + import { MappedModules } from "@moonlight-mod/mappings"; 635 + export const OAuth2AuthorizeModal: MappedModules["discord/modules/oauth2/index"]["OAuth2AuthorizeModal"]; 636 + export const OAuth2AuthorizePage: MappedModules["discord/modules/oauth2/index"]["OAuth2AuthorizePage"]; 637 + export const getOAuth2AuthorizeProps: MappedModules["discord/modules/oauth2/index"]["getOAuth2AuthorizeProps"]; 638 + export const openOAuth2Modal: MappedModules["discord/modules/oauth2/index"]["openOAuth2Modal"]; 639 + export const openOAuth2ModalWithCreateGuildModal: MappedModules["discord/modules/oauth2/index"]["openOAuth2ModalWithCreateGuildModal"]; 640 + export const useOAuth2AuthorizeForm: MappedModules["discord/modules/oauth2/index"]["useOAuth2AuthorizeForm"]; 641 + } 642 + 643 + declare module "@moonlight-mod/wp/discord/modules/people/web/PeoplePage.css" { 644 + import { MappedModules } from "@moonlight-mod/mappings"; 645 + export const addFriend: MappedModules["discord/modules/people/web/PeoplePage.css"]["addFriend"]; 646 + export const badge: MappedModules["discord/modules/people/web/PeoplePage.css"]["badge"]; 647 + export const container: MappedModules["discord/modules/people/web/PeoplePage.css"]["container"]; 648 + export const inviteToolbar: MappedModules["discord/modules/people/web/PeoplePage.css"]["inviteToolbar"]; 649 + export const item: MappedModules["discord/modules/people/web/PeoplePage.css"]["item"]; 650 + export const nowPlayingColumn: MappedModules["discord/modules/people/web/PeoplePage.css"]["nowPlayingColumn"]; 651 + export const peopleColumn: MappedModules["discord/modules/people/web/PeoplePage.css"]["peopleColumn"]; 652 + export const tabBar: MappedModules["discord/modules/people/web/PeoplePage.css"]["tabBar"]; 653 + export const tabBody: MappedModules["discord/modules/people/web/PeoplePage.css"]["tabBody"]; 654 + } 655 + 656 + declare module "@moonlight-mod/wp/discord/modules/user_profile/web/BiteSizeActivity.css" { 657 + import { MappedModules } from "@moonlight-mod/mappings"; 658 + export const header: MappedModules["discord/modules/user_profile/web/BiteSizeActivity.css"]["header"]; 659 + export const headerTag: MappedModules["discord/modules/user_profile/web/BiteSizeActivity.css"]["headerTag"]; 660 + export const body: MappedModules["discord/modules/user_profile/web/BiteSizeActivity.css"]["body"]; 661 + export const footer: MappedModules["discord/modules/user_profile/web/BiteSizeActivity.css"]["footer"]; 662 + export const backdrop: MappedModules["discord/modules/user_profile/web/BiteSizeActivity.css"]["backdrop"]; 663 + export const toast: MappedModules["discord/modules/user_profile/web/BiteSizeActivity.css"]["toast"]; 664 + export const activity: MappedModules["discord/modules/user_profile/web/BiteSizeActivity.css"]["activity"]; 665 + export const upsell: MappedModules["discord/modules/user_profile/web/BiteSizeActivity.css"]["upsell"]; 666 } 667 668 declare module "@moonlight-mod/wp/discord/packages/flux" { 669 import { MappedModules } from "@moonlight-mod/mappings"; 670 + export const BatchedStoreListener: MappedModules["discord/packages/flux"]["BatchedStoreListener"]; 671 + export const Dispatcher: MappedModules["discord/packages/flux"]["Dispatcher"]; 672 + export const Store: MappedModules["discord/packages/flux"]["Store"]; 673 + const _default: MappedModules["discord/packages/flux"]["default"]; 674 + export default _default; 675 + export const statesWillNeverBeEqual: MappedModules["discord/packages/flux"]["statesWillNeverBeEqual"]; 676 + export const useStateFromStores: MappedModules["discord/packages/flux"]["useStateFromStores"]; 677 + export const useStateFromStoresArray: MappedModules["discord/packages/flux"]["useStateFromStoresArray"]; 678 + export const useStateFromStoresObject: MappedModules["discord/packages/flux"]["useStateFromStoresObject"]; 679 + } 680 + 681 + declare module "@moonlight-mod/wp/discord/packages/flux/BatchedStoreListener" { 682 + import { MappedModules } from "@moonlight-mod/mappings"; 683 + const _default: MappedModules["discord/packages/flux/BatchedStoreListener"]["default"]; 684 + export default _default; 685 + } 686 + 687 + declare module "@moonlight-mod/wp/discord/packages/flux/ChangeListeners" { 688 + import { MappedModules } from "@moonlight-mod/mappings"; 689 + const _default: MappedModules["discord/packages/flux/ChangeListeners"]["default"]; 690 + export default _default; 691 + } 692 + 693 + declare module "@moonlight-mod/wp/discord/packages/flux/Dispatcher" { 694 + import { MappedModules } from "@moonlight-mod/mappings"; 695 + export const Dispatcher: MappedModules["discord/packages/flux/Dispatcher"]["Dispatcher"]; 696 + } 697 + 698 + declare module "@moonlight-mod/wp/discord/packages/flux/Emitter" { 699 + import { MappedModules } from "@moonlight-mod/mappings"; 700 + const _default: MappedModules["discord/packages/flux/Emitter"]["default"]; 701 + export default _default; 702 + } 703 + 704 + declare module "@moonlight-mod/wp/discord/packages/flux/LoggingUtils" { 705 + import { MappedModules } from "@moonlight-mod/mappings"; 706 + const _default: MappedModules["discord/packages/flux/LoggingUtils"]["default"]; 707 + export default _default; 708 + } 709 + 710 + declare module "@moonlight-mod/wp/discord/packages/flux/PersistedStore" { 711 + import { MappedModules } from "@moonlight-mod/mappings"; 712 + export const PersistedStore: MappedModules["discord/packages/flux/PersistedStore"]["PersistedStore"]; 713 + } 714 + 715 + declare module "@moonlight-mod/wp/discord/packages/flux/Store" { 716 + import { MappedModules } from "@moonlight-mod/mappings"; 717 + export const Store: MappedModules["discord/packages/flux/Store"]["Store"]; 718 + } 719 + 720 + declare module "@moonlight-mod/wp/discord/packages/flux/connectStores" { 721 + import { MappedModules } from "@moonlight-mod/mappings"; 722 + const _default: MappedModules["discord/packages/flux/connectStores"]["default"]; 723 + export default _default; 724 + } 725 + 726 + declare module "@moonlight-mod/wp/discord/records/UserRecord" { 727 + import { MappedModules } from "@moonlight-mod/mappings"; 728 + const _default: MappedModules["discord/records/UserRecord"]["default"]; 729 + export default _default; 730 + } 731 + 732 + declare module "@moonlight-mod/wp/discord/styles/shared/Margins.css" { 733 + import { MappedModules } from "@moonlight-mod/mappings"; 734 + export const marginReset: MappedModules["discord/styles/shared/Margins.css"]["marginReset"]; 735 + export const marginTop4: MappedModules["discord/styles/shared/Margins.css"]["marginTop4"]; 736 + export const marginBottom4: MappedModules["discord/styles/shared/Margins.css"]["marginBottom4"]; 737 + export const marginTop8: MappedModules["discord/styles/shared/Margins.css"]["marginTop8"]; 738 + export const marginBottom8: MappedModules["discord/styles/shared/Margins.css"]["marginBottom8"]; 739 + export const marginTop20: MappedModules["discord/styles/shared/Margins.css"]["marginTop20"]; 740 + export const marginBottom20: MappedModules["discord/styles/shared/Margins.css"]["marginBottom20"]; 741 + export const marginTop40: MappedModules["discord/styles/shared/Margins.css"]["marginTop40"]; 742 + export const marginBottom40: MappedModules["discord/styles/shared/Margins.css"]["marginBottom40"]; 743 + export const marginTop60: MappedModules["discord/styles/shared/Margins.css"]["marginTop60"]; 744 + export const marginBottom60: MappedModules["discord/styles/shared/Margins.css"]["marginBottom60"]; 745 + export const marginCenterHorz: MappedModules["discord/styles/shared/Margins.css"]["marginCenterHorz"]; 746 + export const marginLeft8: MappedModules["discord/styles/shared/Margins.css"]["marginLeft8"]; 747 } 748 749 declare module "@moonlight-mod/wp/discord/uikit/Flex" { 750 import { MappedModules } from "@moonlight-mod/mappings"; 751 + const _default: MappedModules["discord/uikit/Flex"]["default"]; 752 + export default _default; 753 } 754 755 declare module "@moonlight-mod/wp/discord/utils/ClipboardUtils" { 756 import { MappedModules } from "@moonlight-mod/mappings"; 757 + export const SUPPORTS_COPY: MappedModules["discord/utils/ClipboardUtils"]["SUPPORTS_COPY"]; 758 + export const copy: MappedModules["discord/utils/ClipboardUtils"]["copy"]; 759 + } 760 + 761 + declare module "@moonlight-mod/wp/discord/utils/ComponentDispatchUtils" { 762 + import { MappedModules } from "@moonlight-mod/mappings"; 763 + export const ComponentDispatcher: MappedModules["discord/utils/ComponentDispatchUtils"]["ComponentDispatcher"]; 764 + export const ComponentDispatch: MappedModules["discord/utils/ComponentDispatchUtils"]["ComponentDispatch"]; 765 } 766 767 declare module "@moonlight-mod/wp/discord/utils/HTTPUtils" { 768 import { MappedModules } from "@moonlight-mod/mappings"; 769 + export const HTTP: MappedModules["discord/utils/HTTPUtils"]["HTTP"]; 770 + } 771 + 772 + declare module "@moonlight-mod/wp/discord/utils/MaskedLinkUtils" { 773 + import { MappedModules } from "@moonlight-mod/mappings"; 774 + export const isLinkTrusted: MappedModules["discord/utils/MaskedLinkUtils"]["isLinkTrusted"]; 775 + export const handleClick: MappedModules["discord/utils/MaskedLinkUtils"]["handleClick"]; 776 } 777 778 declare module "@moonlight-mod/wp/discord/utils/NativeUtils" { 779 import { MappedModules } from "@moonlight-mod/mappings"; 780 + const _default: MappedModules["discord/utils/NativeUtils"]["default"]; 781 + export default _default; 782 + } 783 + 784 + declare module "@moonlight-mod/wp/highlight.js" { 785 + import { MappedModules } from "@moonlight-mod/mappings"; 786 + export const highlight: MappedModules["highlight.js"]["highlight"]; 787 + export const highlightAuto: MappedModules["highlight.js"]["highlightAuto"]; 788 + export const fixMarkup: MappedModules["highlight.js"]["fixMarkup"]; 789 + export const highlightBlock: MappedModules["highlight.js"]["highlightBlock"]; 790 + export const configure: MappedModules["highlight.js"]["configure"]; 791 + export const initHighlighting: MappedModules["highlight.js"]["initHighlighting"]; 792 + export const initHighlightingOnLoad: MappedModules["highlight.js"]["initHighlightingOnLoad"]; 793 + export const registerLanguage: MappedModules["highlight.js"]["registerLanguage"]; 794 + export const listLanguages: MappedModules["highlight.js"]["listLanguages"]; 795 + export const getLanguage: MappedModules["highlight.js"]["getLanguage"]; 796 + export const inherit: MappedModules["highlight.js"]["inherit"]; 797 + export const COMMENT: MappedModules["highlight.js"]["COMMENT"]; 798 + export const IDENT_RE: MappedModules["highlight.js"]["IDENT_RE"]; 799 + export const UNDERSCORE_IDENT_RE: MappedModules["highlight.js"]["UNDERSCORE_IDENT_RE"]; 800 + export const NUMBER_RE: MappedModules["highlight.js"]["NUMBER_RE"]; 801 + export const C_NUMBER_RE: MappedModules["highlight.js"]["C_NUMBER_RE"]; 802 + export const BINARY_NUMBER_RE: MappedModules["highlight.js"]["BINARY_NUMBER_RE"]; 803 + export const RE_STARTERS_RE: MappedModules["highlight.js"]["RE_STARTERS_RE"]; 804 + export const BACKSLASH_ESCAPE: MappedModules["highlight.js"]["BACKSLASH_ESCAPE"]; 805 + export const APOS_STRING_MODE: MappedModules["highlight.js"]["APOS_STRING_MODE"]; 806 + export const QUOTE_STRING_MODE: MappedModules["highlight.js"]["QUOTE_STRING_MODE"]; 807 + export const PHRASAL_WORDS_MODE: MappedModules["highlight.js"]["PHRASAL_WORDS_MODE"]; 808 + export const C_LINE_COMMENT_MODE: MappedModules["highlight.js"]["C_LINE_COMMENT_MODE"]; 809 + export const C_BLOCK_COMMENT_MODE: MappedModules["highlight.js"]["C_BLOCK_COMMENT_MODE"]; 810 + export const HASH_COMMENT_MODE: MappedModules["highlight.js"]["HASH_COMMENT_MODE"]; 811 + export const NUMBER_MODE: MappedModules["highlight.js"]["NUMBER_MODE"]; 812 + export const C_NUMBER_MODE: MappedModules["highlight.js"]["C_NUMBER_MODE"]; 813 + export const BINARY_NUMBER_MODE: MappedModules["highlight.js"]["BINARY_NUMBER_MODE"]; 814 + export const CSS_NUMBER_MODE: MappedModules["highlight.js"]["CSS_NUMBER_MODE"]; 815 + export const REGEX_MODE: MappedModules["highlight.js"]["REGEX_MODE"]; 816 + export const TITLE_MODE: MappedModules["highlight.js"]["TITLE_MODE"]; 817 + export const UNDERSCORE_TITLE_MODE: MappedModules["highlight.js"]["UNDERSCORE_TITLE_MODE"]; 818 + const _default: MappedModules["highlight.js"]["default"]; 819 + export default _default; 820 + export const HighlightJS: MappedModules["highlight.js"]["HighlightJS"]; 821 + } 822 + 823 + declare module "@moonlight-mod/wp/highlight.js/lib/core" { 824 + import { MappedModules } from "@moonlight-mod/mappings"; 825 + export const highlight: MappedModules["highlight.js/lib/core"]["highlight"]; 826 + export const highlightAuto: MappedModules["highlight.js/lib/core"]["highlightAuto"]; 827 + export const fixMarkup: MappedModules["highlight.js/lib/core"]["fixMarkup"]; 828 + export const highlightBlock: MappedModules["highlight.js/lib/core"]["highlightBlock"]; 829 + export const configure: MappedModules["highlight.js/lib/core"]["configure"]; 830 + export const initHighlighting: MappedModules["highlight.js/lib/core"]["initHighlighting"]; 831 + export const initHighlightingOnLoad: MappedModules["highlight.js/lib/core"]["initHighlightingOnLoad"]; 832 + export const registerLanguage: MappedModules["highlight.js/lib/core"]["registerLanguage"]; 833 + export const listLanguages: MappedModules["highlight.js/lib/core"]["listLanguages"]; 834 + export const getLanguage: MappedModules["highlight.js/lib/core"]["getLanguage"]; 835 + export const inherit: MappedModules["highlight.js/lib/core"]["inherit"]; 836 + export const COMMENT: MappedModules["highlight.js/lib/core"]["COMMENT"]; 837 + export const IDENT_RE: MappedModules["highlight.js/lib/core"]["IDENT_RE"]; 838 + export const UNDERSCORE_IDENT_RE: MappedModules["highlight.js/lib/core"]["UNDERSCORE_IDENT_RE"]; 839 + export const NUMBER_RE: MappedModules["highlight.js/lib/core"]["NUMBER_RE"]; 840 + export const C_NUMBER_RE: MappedModules["highlight.js/lib/core"]["C_NUMBER_RE"]; 841 + export const BINARY_NUMBER_RE: MappedModules["highlight.js/lib/core"]["BINARY_NUMBER_RE"]; 842 + export const RE_STARTERS_RE: MappedModules["highlight.js/lib/core"]["RE_STARTERS_RE"]; 843 + export const BACKSLASH_ESCAPE: MappedModules["highlight.js/lib/core"]["BACKSLASH_ESCAPE"]; 844 + export const APOS_STRING_MODE: MappedModules["highlight.js/lib/core"]["APOS_STRING_MODE"]; 845 + export const QUOTE_STRING_MODE: MappedModules["highlight.js/lib/core"]["QUOTE_STRING_MODE"]; 846 + export const PHRASAL_WORDS_MODE: MappedModules["highlight.js/lib/core"]["PHRASAL_WORDS_MODE"]; 847 + export const C_LINE_COMMENT_MODE: MappedModules["highlight.js/lib/core"]["C_LINE_COMMENT_MODE"]; 848 + export const C_BLOCK_COMMENT_MODE: MappedModules["highlight.js/lib/core"]["C_BLOCK_COMMENT_MODE"]; 849 + export const HASH_COMMENT_MODE: MappedModules["highlight.js/lib/core"]["HASH_COMMENT_MODE"]; 850 + export const NUMBER_MODE: MappedModules["highlight.js/lib/core"]["NUMBER_MODE"]; 851 + export const C_NUMBER_MODE: MappedModules["highlight.js/lib/core"]["C_NUMBER_MODE"]; 852 + export const BINARY_NUMBER_MODE: MappedModules["highlight.js/lib/core"]["BINARY_NUMBER_MODE"]; 853 + export const CSS_NUMBER_MODE: MappedModules["highlight.js/lib/core"]["CSS_NUMBER_MODE"]; 854 + export const REGEX_MODE: MappedModules["highlight.js/lib/core"]["REGEX_MODE"]; 855 + export const TITLE_MODE: MappedModules["highlight.js/lib/core"]["TITLE_MODE"]; 856 + export const UNDERSCORE_TITLE_MODE: MappedModules["highlight.js/lib/core"]["UNDERSCORE_TITLE_MODE"]; 857 + } 858 + 859 + declare module "@moonlight-mod/wp/lodash" {} 860 + 861 + declare module "@moonlight-mod/wp/murmurhash" { 862 + import { MappedModules } from "@moonlight-mod/mappings"; 863 + export const v2: MappedModules["murmurhash"]["v2"]; 864 + export const v3: MappedModules["murmurhash"]["v3"]; 865 + } 866 + 867 + declare module "@moonlight-mod/wp/platform.js" { 868 + import { MappedModules } from "@moonlight-mod/mappings"; 869 + export const description: MappedModules["platform.js"]["description"]; 870 + export const layout: MappedModules["platform.js"]["layout"]; 871 + export const manufacturer: MappedModules["platform.js"]["manufacturer"]; 872 + export const name: MappedModules["platform.js"]["name"]; 873 + export const prerelease: MappedModules["platform.js"]["prerelease"]; 874 + export const product: MappedModules["platform.js"]["product"]; 875 + export const ua: MappedModules["platform.js"]["ua"]; 876 + export const version: MappedModules["platform.js"]["version"]; 877 + export const os: MappedModules["platform.js"]["os"]; 878 + export const parse: MappedModules["platform.js"]["parse"]; 879 + export const toString: MappedModules["platform.js"]["toString"]; 880 } 881 882 declare module "@moonlight-mod/wp/react" { 883 import { MappedModules } from "@moonlight-mod/mappings"; 884 + const _: Omit<MappedModules["react"], "__mappings_exportEquals">; 885 export = _; 886 } 887 + 888 + declare module "@moonlight-mod/wp/uuid/v4" {}
+7 -7
packages/types/tsconfig.json
··· 1 { 2 "compilerOptions": { 3 - "target": "es2016", 4 - "module": "es6", 5 - "esModuleInterop": true, 6 - "forceConsistentCasingInFileNames": true, 7 - "strict": true, 8 - "moduleResolution": "bundler", 9 "jsx": "react", 10 - "declaration": true 11 }, 12 "include": ["./src/**/*", "src/index.ts", "./src/import.d.ts"] 13 }
··· 1 { 2 "compilerOptions": { 3 + "target": "ES2016", 4 "jsx": "react", 5 + "module": "ES6", 6 + "moduleResolution": "bundler", 7 + "strict": true, 8 + "declaration": true, 9 + "esModuleInterop": true, 10 + "forceConsistentCasingInFileNames": true 11 }, 12 "include": ["./src/**/*", "src/index.ts", "./src/import.d.ts"] 13 }
+10 -3
packages/web-preload/package.json
··· 2 "name": "@moonlight-mod/web-preload", 3 "private": true, 4 "main": "src/index.ts", 5 "dependencies": { 6 "@moonlight-mod/core": "workspace:*", 7 - "@moonlight-mod/lunast": "^1.0.0", 8 - "@moonlight-mod/mappings": "^1.0.10", 9 - "@moonlight-mod/moonmap": "^1.0.3", 10 "@moonlight-mod/types": "workspace:*" 11 } 12 }
··· 2 "name": "@moonlight-mod/web-preload", 3 "private": true, 4 "main": "src/index.ts", 5 + "engineStrict": true, 6 + "engines": { 7 + "node": ">=22", 8 + "pnpm": ">=10", 9 + "npm": "pnpm", 10 + "yarn": "pnpm" 11 + }, 12 "dependencies": { 13 "@moonlight-mod/core": "workspace:*", 14 + "@moonlight-mod/lunast": "catalog:prod", 15 + "@moonlight-mod/mappings": "catalog:prod", 16 + "@moonlight-mod/moonmap": "catalog:prod", 17 "@moonlight-mod/types": "workspace:*" 18 } 19 }
+2 -2
packages/web-preload/src/index.ts
··· 7 import Moonmap from "@moonlight-mod/moonmap"; 8 import loadMappings from "@moonlight-mod/mappings"; 9 import { createEventEmitter } from "@moonlight-mod/core/util/event"; 10 - import { EventPayloads, EventType } from "@moonlight-mod/types/core/event"; 11 12 async function load() { 13 delete window._moonlightWebLoad; ··· 20 pendingModules: new Set(), 21 enabledExtensions: new Set(), 22 23 - events: createEventEmitter<EventType, EventPayloads>(), 24 patchingInternals: { 25 onModuleLoad, 26 registerPatch,
··· 7 import Moonmap from "@moonlight-mod/moonmap"; 8 import loadMappings from "@moonlight-mod/mappings"; 9 import { createEventEmitter } from "@moonlight-mod/core/util/event"; 10 + import { WebEventPayloads, WebEventType } from "@moonlight-mod/types/core/event"; 11 12 async function load() { 13 delete window._moonlightWebLoad; ··· 20 pendingModules: new Set(), 21 enabledExtensions: new Set(), 22 23 + events: createEventEmitter<WebEventType, WebEventPayloads>(), 24 patchingInternals: { 25 onModuleLoad, 26 registerPatch,
+4 -1
packages/web-preload/tsconfig.json
··· 1 { 2 - "extends": "../../tsconfig.json" 3 }
··· 1 { 2 + "extends": "../../tsconfig.json", 3 + "compilerOptions": { 4 + "lib": ["ESNext", "DOM"] 5 + } 6 }
+1243 -729
pnpm-lock.yaml
··· 4 autoInstallPeers: true 5 excludeLinksFromLockfile: false 6 7 importers: 8 9 .: 10 devDependencies: 11 '@moonlight-mod/eslint-config': 12 - specifier: github:moonlight-mod/eslint-config 13 - version: https://codeload.github.com/moonlight-mod/eslint-config/tar.gz/e262ac24e1a0955a9b3e0d66da247a0a8c0446c9(eslint@9.12.0)(prettier@3.1.0)(typescript@5.3.2) 14 esbuild: 15 - specifier: ^0.19.3 16 version: 0.19.3 17 esbuild-copy-static-files: 18 - specifier: ^0.1.0 19 version: 0.1.0 20 eslint: 21 - specifier: ^9.12.0 22 - version: 9.12.0 23 husky: 24 - specifier: ^8.0.3 25 version: 8.0.3 26 prettier: 27 - specifier: ^3.1.0 28 version: 3.1.0 29 typescript: 30 - specifier: ^5.3.2 31 - version: 5.3.2 32 33 packages/browser: 34 dependencies: ··· 42 specifier: workspace:* 43 version: link:../web-preload 44 '@zenfs/core': 45 - specifier: ^1.0.2 46 - version: 1.0.2 47 '@zenfs/dom': 48 - specifier: ^0.2.16 49 - version: 0.2.16(@zenfs/core@1.0.2) 50 51 packages/core: 52 dependencies: ··· 63 specifier: workspace:* 64 version: link:../types 65 microdiff: 66 - specifier: ^1.5.0 67 version: 1.5.0 68 nanotar: 69 - specifier: ^0.1.1 70 version: 0.1.1 71 72 packages/injector: ··· 90 packages/types: 91 dependencies: 92 '@moonlight-mod/lunast': 93 - specifier: ^1.0.0 94 - version: 1.0.0 95 '@moonlight-mod/mappings': 96 - specifier: ^1.0.10 97 - version: 1.0.10(@moonlight-mod/lunast@1.0.0)(@moonlight-mod/moonmap@1.0.3) 98 '@moonlight-mod/moonmap': 99 - specifier: ^1.0.3 100 - version: 1.0.3 101 '@types/react': 102 specifier: ^18.3.10 103 - version: 18.3.10 104 csstype: 105 - specifier: ^3.1.2 106 - version: 3.1.2 107 standalone-electron-types: 108 specifier: ^1.0.0 109 version: 1.0.0 ··· 114 specifier: workspace:* 115 version: link:../core 116 '@moonlight-mod/lunast': 117 - specifier: ^1.0.0 118 - version: 1.0.0 119 '@moonlight-mod/mappings': 120 - specifier: ^1.0.10 121 - version: 1.0.10(@moonlight-mod/lunast@1.0.0)(@moonlight-mod/moonmap@1.0.3) 122 '@moonlight-mod/moonmap': 123 - specifier: ^1.0.3 124 - version: 1.0.3 125 '@moonlight-mod/types': 126 specifier: workspace:* 127 version: link:../types ··· 131 '@aashutoshrathi/word-wrap@1.2.6': 132 resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} 133 engines: {node: '>=0.10.0'} 134 135 '@esbuild/android-arm64@0.19.3': 136 resolution: {integrity: sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==} ··· 264 cpu: [x64] 265 os: [win32] 266 267 - '@eslint-community/eslint-utils@4.4.0': 268 - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} 269 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 270 peerDependencies: 271 eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 272 273 - '@eslint-community/regexpp@4.11.1': 274 - resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} 275 engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 276 277 - '@eslint/config-array@0.18.0': 278 - resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} 279 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 280 281 - '@eslint/core@0.6.0': 282 - resolution: {integrity: sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==} 283 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 284 285 - '@eslint/eslintrc@3.1.0': 286 - resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} 287 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 288 289 - '@eslint/js@9.12.0': 290 - resolution: {integrity: sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==} 291 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 292 293 - '@eslint/object-schema@2.1.4': 294 - resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} 295 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 296 297 - '@eslint/plugin-kit@0.2.0': 298 - resolution: {integrity: sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==} 299 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 300 301 - '@humanfs/core@0.19.0': 302 - resolution: {integrity: sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==} 303 engines: {node: '>=18.18.0'} 304 305 - '@humanfs/node@0.16.5': 306 - resolution: {integrity: sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==} 307 engines: {node: '>=18.18.0'} 308 309 '@humanwhocodes/module-importer@1.0.1': ··· 314 resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} 315 engines: {node: '>=18.18'} 316 317 '@moonlight-mod/eslint-config@https://codeload.github.com/moonlight-mod/eslint-config/tar.gz/e262ac24e1a0955a9b3e0d66da247a0a8c0446c9': 318 resolution: {tarball: https://codeload.github.com/moonlight-mod/eslint-config/tar.gz/e262ac24e1a0955a9b3e0d66da247a0a8c0446c9} 319 version: 1.0.1 ··· 321 eslint: '>= 9' 322 typescript: '>= 5.3' 323 324 - '@moonlight-mod/lunast@1.0.0': 325 - resolution: {integrity: sha512-kJgf41K12i6/2LbXK97CNO+pNO7ADGh9N4bCQcOPwosocKMcwKHDEZUgPqeihNshY3c3AEW1LiyXjlsl24PdDw==} 326 327 - '@moonlight-mod/mappings@1.0.10': 328 - resolution: {integrity: sha512-L04To4MhlxOWxvvfVIRwj7d8H5qHthjUfikSx9WMk60qt67+6dFzN9CoAG9uG5l1B27IIEG3voVXBr0oSkooYw==} 329 peerDependencies: 330 - '@moonlight-mod/lunast': ^1.0.0 331 - '@moonlight-mod/moonmap': ^1.0.0 332 333 - '@moonlight-mod/moonmap@1.0.3': 334 - resolution: {integrity: sha512-G7pwvrcVDimc388IX6VZFzBXpbuyvqbJ+w9/v+MUIc8P7dADJXQ9YkBWvobtRc6eaBBl1FWUwTeU8oobbxLVag==} 335 336 '@nodelib/fs.scandir@2.1.5': 337 resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} ··· 345 resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 346 engines: {node: '>= 8'} 347 348 - '@pkgr/core@0.1.1': 349 - resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} 350 engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} 351 352 '@types/estree-jsx@1.0.5': 353 resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} ··· 355 '@types/estree@1.0.6': 356 resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 357 358 '@types/fbemitter@2.0.35': 359 resolution: {integrity: sha512-Xem6d7qUfmouCHntCrRYgDBwbf+WWRd6G+7WEFlEZFZ67LZXiYRvT2LV8wcZa6mIaAil95+ABQdKgB6hPIsnng==} 360 361 '@types/flux@3.1.14': 362 resolution: {integrity: sha512-WRXN0kQPCnqxN0/PgNgc7WBF6c8rbSHsEep3/qBLpsQ824RONdOmTs0TV7XhIW2GDNRAHO2CqCgAFLR5PChosw==} 363 364 '@types/json-schema@7.0.15': 365 resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 366 367 '@types/node@18.17.17': 368 resolution: {integrity: sha512-cOxcXsQ2sxiwkykdJqvyFS+MLQPLvIdwh5l6gNg8qF6s+C7XSkEWOZjK+XhUZd+mYvHV/180g2cnCcIl4l06Pw==} 369 370 - '@types/node@20.16.10': 371 - resolution: {integrity: sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==} 372 373 '@types/prop-types@15.7.13': 374 resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} 375 376 - '@types/react@18.3.10': 377 - resolution: {integrity: sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg==} 378 379 - '@types/readable-stream@4.0.15': 380 - resolution: {integrity: sha512-oAZ3kw+kJFkEqyh7xORZOku1YAKvsFTogRY8kVl4vHpEKiDkfnSA/My8haRE7fvmix5Zyy+1pwzOi7yycGLBJw==} 381 - 382 - '@typescript-eslint/eslint-plugin@8.8.1': 383 - resolution: {integrity: sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==} 384 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 385 peerDependencies: 386 '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 387 eslint: ^8.57.0 || ^9.0.0 388 - typescript: '*' 389 - peerDependenciesMeta: 390 - typescript: 391 - optional: true 392 393 - '@typescript-eslint/parser@8.8.1': 394 - resolution: {integrity: sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==} 395 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 396 peerDependencies: 397 eslint: ^8.57.0 || ^9.0.0 398 - typescript: '*' 399 - peerDependenciesMeta: 400 - typescript: 401 - optional: true 402 403 - '@typescript-eslint/scope-manager@8.8.1': 404 - resolution: {integrity: sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==} 405 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 406 407 - '@typescript-eslint/type-utils@8.8.1': 408 - resolution: {integrity: sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==} 409 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 410 peerDependencies: 411 - typescript: '*' 412 - peerDependenciesMeta: 413 - typescript: 414 - optional: true 415 416 - '@typescript-eslint/types@8.8.1': 417 - resolution: {integrity: sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==} 418 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 419 420 - '@typescript-eslint/typescript-estree@8.8.1': 421 - resolution: {integrity: sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==} 422 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 423 peerDependencies: 424 - typescript: '*' 425 - peerDependenciesMeta: 426 - typescript: 427 - optional: true 428 429 - '@typescript-eslint/utils@8.8.1': 430 - resolution: {integrity: sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==} 431 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 432 peerDependencies: 433 eslint: ^8.57.0 || ^9.0.0 434 435 - '@typescript-eslint/visitor-keys@8.8.1': 436 - resolution: {integrity: sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==} 437 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 438 439 - '@zenfs/core@1.0.2': 440 - resolution: {integrity: sha512-LMTD4ntn6Ag1y+IeOSVykDDvYC12dsGFtsX8M/54OQrLs7v+YnX4bpo0o2osbm8XFmU2MTNMX/G3PLsvzgWzrg==} 441 - engines: {node: '>= 16'} 442 hasBin: true 443 444 - '@zenfs/dom@0.2.16': 445 - resolution: {integrity: sha512-6Ev+ol9hZIgQECNZR+xxjQ/a99EhhrWeiQttm/+U7YJK3HdTjiKfU39DsfGeH64vSqhpa5Vj+LWRx75SHkjw0Q==} 446 engines: {node: '>= 18'} 447 peerDependencies: 448 - '@zenfs/core': ^1.0.0 449 450 abort-controller@3.0.0: 451 resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} ··· 456 peerDependencies: 457 acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 458 459 - acorn@8.12.1: 460 - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} 461 engines: {node: '>=0.4.0'} 462 hasBin: true 463 ··· 468 resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 469 engines: {node: '>=8'} 470 471 argparse@2.0.1: 472 resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 473 474 - array-buffer-byte-length@1.0.1: 475 - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} 476 engines: {node: '>= 0.4'} 477 478 array-includes@3.1.8: ··· 483 resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} 484 engines: {node: '>= 0.4'} 485 486 - array.prototype.flat@1.3.2: 487 - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} 488 engines: {node: '>= 0.4'} 489 490 - array.prototype.flatmap@1.3.2: 491 - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} 492 engines: {node: '>= 0.4'} 493 494 array.prototype.tosorted@1.1.4: 495 resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} 496 engines: {node: '>= 0.4'} 497 498 - arraybuffer.prototype.slice@1.0.3: 499 - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} 500 engines: {node: '>= 0.4'} 501 502 astring@1.9.0: 503 resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} 504 hasBin: true 505 506 available-typed-arrays@1.0.7: 507 resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} ··· 526 buffer@6.0.3: 527 resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} 528 529 - call-bind@1.0.7: 530 - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} 531 engines: {node: '>= 0.4'} 532 533 callsites@3.1.0: ··· 548 concat-map@0.0.1: 549 resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 550 551 - cross-spawn@7.0.3: 552 - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 553 engines: {node: '>= 8'} 554 555 - csstype@3.1.2: 556 - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} 557 - 558 csstype@3.1.3: 559 resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 560 561 - data-view-buffer@1.0.1: 562 - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} 563 engines: {node: '>= 0.4'} 564 565 - data-view-byte-length@1.0.1: 566 - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} 567 engines: {node: '>= 0.4'} 568 569 - data-view-byte-offset@1.0.0: 570 - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} 571 engines: {node: '>= 0.4'} 572 573 - debug@4.3.4: 574 - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 575 engines: {node: '>=6.0'} 576 peerDependencies: 577 supports-color: '*' ··· 590 resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} 591 engines: {node: '>= 0.4'} 592 593 doctrine@2.1.0: 594 resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} 595 engines: {node: '>=0.10.0'} 596 597 - es-abstract@1.23.3: 598 - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} 599 engines: {node: '>= 0.4'} 600 601 - es-define-property@1.0.0: 602 - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} 603 engines: {node: '>= 0.4'} 604 605 es-errors@1.3.0: 606 resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} 607 engines: {node: '>= 0.4'} 608 609 - es-iterator-helpers@1.1.0: 610 - resolution: {integrity: sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==} 611 engines: {node: '>= 0.4'} 612 613 - es-object-atoms@1.0.0: 614 - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} 615 engines: {node: '>= 0.4'} 616 617 - es-set-tostringtag@2.0.3: 618 - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} 619 engines: {node: '>= 0.4'} 620 621 - es-shim-unscopables@1.0.2: 622 - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} 623 624 - es-to-primitive@1.2.1: 625 - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} 626 engines: {node: '>= 0.4'} 627 628 esbuild-copy-static-files@0.1.0: ··· 643 peerDependencies: 644 eslint: '>=7.0.0' 645 646 - eslint-plugin-prettier@5.2.1: 647 - resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} 648 engines: {node: ^14.18.0 || >=16.0.0} 649 peerDependencies: 650 '@types/eslint': '>=8.0.0' 651 eslint: '>=8.0.0' 652 - eslint-config-prettier: '*' 653 prettier: '>=3.0.0' 654 peerDependenciesMeta: 655 '@types/eslint': ··· 657 eslint-config-prettier: 658 optional: true 659 660 - eslint-plugin-react@7.37.1: 661 - resolution: {integrity: sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==} 662 engines: {node: '>=4'} 663 peerDependencies: 664 eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 665 666 - eslint-scope@8.1.0: 667 - resolution: {integrity: sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==} 668 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 669 670 eslint-visitor-keys@3.4.3: 671 resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 672 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 673 674 - eslint-visitor-keys@4.1.0: 675 - resolution: {integrity: sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==} 676 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 677 678 - eslint@9.12.0: 679 - resolution: {integrity: sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==} 680 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 681 hasBin: true 682 peerDependencies: ··· 685 jiti: 686 optional: true 687 688 - espree@10.2.0: 689 - resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} 690 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 691 692 - esquery@1.5.0: 693 - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} 694 engines: {node: '>=0.10'} 695 696 esrecurse@4.3.0: ··· 738 fastq@1.17.1: 739 resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} 740 741 file-entry-cache@8.0.0: 742 resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} 743 engines: {node: '>=16.0.0'} ··· 746 resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 747 engines: {node: '>=8'} 748 749 find-up@5.0.0: 750 resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 751 engines: {node: '>=10'} ··· 757 flatted@3.2.9: 758 resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} 759 760 - for-each@0.3.3: 761 - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} 762 763 function-bind@1.1.2: 764 resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 765 766 - function.prototype.name@1.1.6: 767 - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} 768 engines: {node: '>= 0.4'} 769 770 functions-have-names@1.2.3: 771 resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} 772 773 - get-intrinsic@1.2.4: 774 - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} 775 engines: {node: '>= 0.4'} 776 777 - get-symbol-description@1.0.2: 778 - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} 779 engines: {node: '>= 0.4'} 780 781 glob-parent@5.1.2: ··· 794 resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} 795 engines: {node: '>= 0.4'} 796 797 - gopd@1.0.1: 798 - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} 799 800 graphemer@1.4.0: 801 resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 802 803 - has-bigints@1.0.2: 804 - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} 805 806 has-flag@4.0.0: 807 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} ··· 810 has-property-descriptors@1.0.2: 811 resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} 812 813 - has-proto@1.0.3: 814 - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} 815 engines: {node: '>= 0.4'} 816 817 - has-symbols@1.0.3: 818 - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} 819 engines: {node: '>= 0.4'} 820 821 has-tostringtag@1.0.2: ··· 834 ieee754@1.2.1: 835 resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 836 837 - ignore@5.3.0: 838 - resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} 839 - engines: {node: '>= 4'} 840 - 841 ignore@5.3.2: 842 resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 843 engines: {node: '>= 4'} ··· 850 resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 851 engines: {node: '>=0.8.19'} 852 853 - internal-slot@1.0.7: 854 - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} 855 engines: {node: '>= 0.4'} 856 857 - is-array-buffer@3.0.4: 858 - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} 859 engines: {node: '>= 0.4'} 860 861 - is-async-function@2.0.0: 862 - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} 863 engines: {node: '>= 0.4'} 864 865 - is-bigint@1.0.4: 866 - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} 867 868 - is-boolean-object@1.1.2: 869 - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} 870 engines: {node: '>= 0.4'} 871 872 is-callable@1.2.7: 873 resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} 874 engines: {node: '>= 0.4'} 875 876 - is-core-module@2.15.1: 877 - resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} 878 engines: {node: '>= 0.4'} 879 880 - is-data-view@1.0.1: 881 - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} 882 engines: {node: '>= 0.4'} 883 884 - is-date-object@1.0.5: 885 - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} 886 engines: {node: '>= 0.4'} 887 888 is-extglob@2.1.1: 889 resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 890 engines: {node: '>=0.10.0'} 891 892 - is-finalizationregistry@1.0.2: 893 - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} 894 895 - is-generator-function@1.0.10: 896 - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} 897 engines: {node: '>= 0.4'} 898 899 is-glob@4.0.3: ··· 904 resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} 905 engines: {node: '>= 0.4'} 906 907 - is-negative-zero@2.0.3: 908 - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} 909 - engines: {node: '>= 0.4'} 910 - 911 - is-number-object@1.0.7: 912 - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} 913 engines: {node: '>= 0.4'} 914 915 is-number@7.0.0: 916 resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 917 engines: {node: '>=0.12.0'} 918 919 - is-regex@1.1.4: 920 - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} 921 engines: {node: '>= 0.4'} 922 923 is-set@2.0.3: 924 resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} 925 engines: {node: '>= 0.4'} 926 927 - is-shared-array-buffer@1.0.3: 928 - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} 929 engines: {node: '>= 0.4'} 930 931 - is-string@1.0.7: 932 - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} 933 engines: {node: '>= 0.4'} 934 935 - is-symbol@1.0.4: 936 - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} 937 engines: {node: '>= 0.4'} 938 939 - is-typed-array@1.1.13: 940 - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} 941 engines: {node: '>= 0.4'} 942 943 is-weakmap@2.0.2: 944 resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} 945 engines: {node: '>= 0.4'} 946 947 - is-weakref@1.0.2: 948 - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} 949 950 - is-weakset@2.0.3: 951 - resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} 952 engines: {node: '>= 0.4'} 953 954 isarray@2.0.5: ··· 957 isexe@2.0.0: 958 resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 959 960 - iterator.prototype@1.1.3: 961 - resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==} 962 engines: {node: '>= 0.4'} 963 964 js-tokens@4.0.0: 965 resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 966 ··· 999 resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 1000 hasBin: true 1001 1002 merge2@1.4.1: 1003 resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1004 engines: {node: '>= 8'} ··· 1014 resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1015 engines: {node: '>=8.6'} 1016 1017 minimatch@3.1.2: 1018 resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1019 ··· 1021 resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1022 engines: {node: '>=16 || 14 >=14.17'} 1023 1024 - ms@2.1.2: 1025 - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 1026 1027 nanotar@0.1.1: 1028 resolution: {integrity: sha512-AiJsGsSF3O0havL1BydvI4+wR76sKT+okKRwWIaK96cZUnXqH0uNBOsHlbwZq3+m2BR1VKqHDVudl3gO4mYjpQ==} ··· 1030 natural-compare@1.4.0: 1031 resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1032 1033 object-assign@4.1.1: 1034 resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1035 engines: {node: '>=0.10.0'} 1036 1037 - object-inspect@1.13.2: 1038 - resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} 1039 engines: {node: '>= 0.4'} 1040 1041 object-keys@1.1.1: 1042 resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} 1043 engines: {node: '>= 0.4'} 1044 1045 - object.assign@4.1.5: 1046 - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} 1047 engines: {node: '>= 0.4'} 1048 1049 - object.entries@1.1.8: 1050 - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} 1051 engines: {node: '>= 0.4'} 1052 1053 object.fromentries@2.0.8: 1054 resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} 1055 engines: {node: '>= 0.4'} 1056 1057 - object.values@1.2.0: 1058 - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} 1059 engines: {node: '>= 0.4'} 1060 1061 optionator@0.9.3: 1062 resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} 1063 engines: {node: '>= 0.8.0'} 1064 1065 p-limit@3.1.0: 1066 resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1067 engines: {node: '>=10'} ··· 1069 p-locate@5.0.0: 1070 resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1071 engines: {node: '>=10'} 1072 1073 parent-module@1.0.1: 1074 resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} ··· 1085 path-parse@1.0.7: 1086 resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1087 1088 picomatch@2.3.1: 1089 resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1090 engines: {node: '>=8.6'} 1091 1092 - possible-typed-array-names@1.0.0: 1093 - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} 1094 engines: {node: '>= 0.4'} 1095 1096 prelude-ls@1.2.1: ··· 1117 resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1118 engines: {node: '>=6'} 1119 1120 queue-microtask@1.2.3: 1121 resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1122 ··· 1127 resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} 1128 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1129 1130 - reflect.getprototypeof@1.0.6: 1131 - resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} 1132 engines: {node: '>= 0.4'} 1133 1134 - regexp.prototype.flags@1.5.3: 1135 - resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} 1136 engines: {node: '>= 0.4'} 1137 1138 resolve-from@4.0.0: ··· 1143 resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} 1144 hasBin: true 1145 1146 reusify@1.0.4: 1147 resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1148 engines: {iojs: '>=1.0.0', node: '>=0.10.0'} ··· 1150 run-parallel@1.2.0: 1151 resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1152 1153 - safe-array-concat@1.1.2: 1154 - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} 1155 engines: {node: '>=0.4'} 1156 1157 - safe-buffer@5.1.2: 1158 - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} 1159 - 1160 safe-buffer@5.2.1: 1161 resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1162 1163 - safe-regex-test@1.0.3: 1164 - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} 1165 engines: {node: '>= 0.4'} 1166 1167 semver@6.3.1: 1168 resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 1169 hasBin: true 1170 1171 - semver@7.6.3: 1172 - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} 1173 engines: {node: '>=10'} 1174 hasBin: true 1175 ··· 1181 resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} 1182 engines: {node: '>= 0.4'} 1183 1184 shebang-command@2.0.0: 1185 resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1186 engines: {node: '>=8'} ··· 1189 resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1190 engines: {node: '>=8'} 1191 1192 - side-channel@1.0.6: 1193 - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} 1194 engines: {node: '>= 0.4'} 1195 1196 standalone-electron-types@1.0.0: 1197 resolution: {integrity: sha512-0HOi/tlTz3mjWhsAz4uRbpQcHMZ+ifj1JzWW9nugykOHClBBG77ps8QinrzX1eow4Iw2pnC+RFaSYRgufF4BOg==} 1198 1199 - string.prototype.matchall@4.0.11: 1200 - resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} 1201 engines: {node: '>= 0.4'} 1202 1203 string.prototype.repeat@1.0.0: 1204 resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} 1205 1206 - string.prototype.trim@1.2.9: 1207 - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} 1208 engines: {node: '>= 0.4'} 1209 1210 - string.prototype.trimend@1.0.8: 1211 - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} 1212 1213 string.prototype.trimstart@1.0.8: 1214 resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} ··· 1229 resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1230 engines: {node: '>= 0.4'} 1231 1232 - synckit@0.9.2: 1233 - resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} 1234 engines: {node: ^14.18.0 || >=16.0.0} 1235 1236 - text-table@0.2.0: 1237 - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 1238 1239 to-regex-range@5.0.1: 1240 resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1241 engines: {node: '>=8.0'} 1242 1243 - ts-api-utils@1.3.0: 1244 - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} 1245 - engines: {node: '>=16'} 1246 peerDependencies: 1247 - typescript: '>=4.2.0' 1248 1249 - tslib@2.7.0: 1250 - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} 1251 1252 type-check@0.4.0: 1253 resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1254 engines: {node: '>= 0.8.0'} 1255 1256 - typed-array-buffer@1.0.2: 1257 - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} 1258 engines: {node: '>= 0.4'} 1259 1260 - typed-array-byte-length@1.0.1: 1261 - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} 1262 engines: {node: '>= 0.4'} 1263 1264 - typed-array-byte-offset@1.0.2: 1265 - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} 1266 engines: {node: '>= 0.4'} 1267 1268 - typed-array-length@1.0.6: 1269 - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} 1270 engines: {node: '>= 0.4'} 1271 1272 - typescript-eslint@8.8.1: 1273 - resolution: {integrity: sha512-R0dsXFt6t4SAFjUSKFjMh4pXDtq04SsFKCVGDP3ZOzNP7itF0jBcZYU4fMsZr4y7O7V7Nc751dDeESbe4PbQMQ==} 1274 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 1275 peerDependencies: 1276 - typescript: '*' 1277 - peerDependenciesMeta: 1278 - typescript: 1279 - optional: true 1280 1281 - typescript@5.3.2: 1282 - resolution: {integrity: sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==} 1283 engines: {node: '>=14.17'} 1284 hasBin: true 1285 1286 - unbox-primitive@1.0.2: 1287 - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} 1288 1289 - undici-types@6.19.8: 1290 - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} 1291 1292 uri-js@4.4.1: 1293 resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1294 1295 - utilium@0.7.1: 1296 - resolution: {integrity: sha512-2ocvTkI7U8LERmwxL0LhFUvEfN66UqcjF6tMiURvUwSyU7U1QC9gST+3iSUSiGccFfnP3f2EXwHNXOnOzx+lAg==} 1297 1298 - which-boxed-primitive@1.0.2: 1299 - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} 1300 1301 - which-builtin-type@1.1.4: 1302 - resolution: {integrity: sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==} 1303 engines: {node: '>= 0.4'} 1304 1305 which-collection@1.0.2: 1306 resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} 1307 engines: {node: '>= 0.4'} 1308 1309 - which-typed-array@1.1.15: 1310 - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} 1311 engines: {node: '>= 0.4'} 1312 1313 which@2.0.2: ··· 1315 engines: {node: '>= 8'} 1316 hasBin: true 1317 1318 yocto-queue@0.1.0: 1319 resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1320 engines: {node: '>=10'} 1321 1322 snapshots: 1323 1324 '@aashutoshrathi/word-wrap@1.2.6': {} 1325 1326 '@esbuild/android-arm64@0.19.3': 1327 optional: true ··· 1389 '@esbuild/win32-x64@0.19.3': 1390 optional: true 1391 1392 - '@eslint-community/eslint-utils@4.4.0(eslint@9.12.0)': 1393 dependencies: 1394 - eslint: 9.12.0 1395 eslint-visitor-keys: 3.4.3 1396 1397 - '@eslint-community/regexpp@4.11.1': {} 1398 1399 - '@eslint/config-array@0.18.0': 1400 dependencies: 1401 - '@eslint/object-schema': 2.1.4 1402 - debug: 4.3.4 1403 minimatch: 3.1.2 1404 transitivePeerDependencies: 1405 - supports-color 1406 1407 - '@eslint/core@0.6.0': {} 1408 1409 - '@eslint/eslintrc@3.1.0': 1410 dependencies: 1411 ajv: 6.12.6 1412 - debug: 4.3.4 1413 - espree: 10.2.0 1414 globals: 14.0.0 1415 - ignore: 5.3.0 1416 import-fresh: 3.3.0 1417 js-yaml: 4.1.0 1418 minimatch: 3.1.2 ··· 1420 transitivePeerDependencies: 1421 - supports-color 1422 1423 - '@eslint/js@9.12.0': {} 1424 1425 - '@eslint/object-schema@2.1.4': {} 1426 1427 - '@eslint/plugin-kit@0.2.0': 1428 dependencies: 1429 levn: 0.4.1 1430 1431 - '@humanfs/core@0.19.0': {} 1432 1433 - '@humanfs/node@0.16.5': 1434 dependencies: 1435 - '@humanfs/core': 0.19.0 1436 '@humanwhocodes/retry': 0.3.1 1437 1438 '@humanwhocodes/module-importer@1.0.1': {} 1439 1440 '@humanwhocodes/retry@0.3.1': {} 1441 1442 - '@moonlight-mod/eslint-config@https://codeload.github.com/moonlight-mod/eslint-config/tar.gz/e262ac24e1a0955a9b3e0d66da247a0a8c0446c9(eslint@9.12.0)(prettier@3.1.0)(typescript@5.3.2)': 1443 dependencies: 1444 - '@eslint/js': 9.12.0 1445 - eslint: 9.12.0 1446 - eslint-config-prettier: 9.1.0(eslint@9.12.0) 1447 - eslint-plugin-prettier: 5.2.1(eslint-config-prettier@9.1.0(eslint@9.12.0))(eslint@9.12.0)(prettier@3.1.0) 1448 - eslint-plugin-react: 7.37.1(eslint@9.12.0) 1449 - typescript: 5.3.2 1450 - typescript-eslint: 8.8.1(eslint@9.12.0)(typescript@5.3.2) 1451 transitivePeerDependencies: 1452 - '@types/eslint' 1453 - prettier 1454 - supports-color 1455 1456 - '@moonlight-mod/lunast@1.0.0': 1457 dependencies: 1458 astring: 1.9.0 1459 estree-toolkit: 1.7.8 1460 meriyah: 6.0.1 1461 1462 - '@moonlight-mod/mappings@1.0.10(@moonlight-mod/lunast@1.0.0)(@moonlight-mod/moonmap@1.0.3)': 1463 dependencies: 1464 - '@moonlight-mod/lunast': 1.0.0 1465 - '@moonlight-mod/moonmap': 1.0.3 1466 '@types/flux': 3.1.14 1467 - '@types/react': 18.3.10 1468 csstype: 3.1.3 1469 1470 - '@moonlight-mod/moonmap@1.0.3': {} 1471 1472 '@nodelib/fs.scandir@2.1.5': 1473 dependencies: ··· 1481 '@nodelib/fs.scandir': 2.1.5 1482 fastq: 1.17.1 1483 1484 - '@pkgr/core@0.1.1': {} 1485 1486 '@types/estree-jsx@1.0.5': 1487 dependencies: 1488 '@types/estree': 1.0.6 1489 1490 '@types/estree@1.0.6': {} 1491 1492 '@types/fbemitter@2.0.35': {} 1493 1494 '@types/flux@3.1.14': 1495 dependencies: 1496 '@types/fbemitter': 2.0.35 1497 - '@types/react': 18.3.10 1498 1499 '@types/json-schema@7.0.15': {} 1500 1501 '@types/node@18.17.17': {} 1502 1503 - '@types/node@20.16.10': 1504 dependencies: 1505 - undici-types: 6.19.8 1506 1507 '@types/prop-types@15.7.13': {} 1508 1509 - '@types/react@18.3.10': 1510 dependencies: 1511 '@types/prop-types': 15.7.13 1512 csstype: 3.1.3 1513 1514 - '@types/readable-stream@4.0.15': 1515 - dependencies: 1516 - '@types/node': 20.16.10 1517 - safe-buffer: 5.1.2 1518 - 1519 - '@typescript-eslint/eslint-plugin@8.8.1(@typescript-eslint/parser@8.8.1(eslint@9.12.0)(typescript@5.3.2))(eslint@9.12.0)(typescript@5.3.2)': 1520 dependencies: 1521 - '@eslint-community/regexpp': 4.11.1 1522 - '@typescript-eslint/parser': 8.8.1(eslint@9.12.0)(typescript@5.3.2) 1523 - '@typescript-eslint/scope-manager': 8.8.1 1524 - '@typescript-eslint/type-utils': 8.8.1(eslint@9.12.0)(typescript@5.3.2) 1525 - '@typescript-eslint/utils': 8.8.1(eslint@9.12.0)(typescript@5.3.2) 1526 - '@typescript-eslint/visitor-keys': 8.8.1 1527 - eslint: 9.12.0 1528 graphemer: 1.4.0 1529 ignore: 5.3.2 1530 natural-compare: 1.4.0 1531 - ts-api-utils: 1.3.0(typescript@5.3.2) 1532 - optionalDependencies: 1533 - typescript: 5.3.2 1534 transitivePeerDependencies: 1535 - supports-color 1536 1537 - '@typescript-eslint/parser@8.8.1(eslint@9.12.0)(typescript@5.3.2)': 1538 dependencies: 1539 - '@typescript-eslint/scope-manager': 8.8.1 1540 - '@typescript-eslint/types': 8.8.1 1541 - '@typescript-eslint/typescript-estree': 8.8.1(typescript@5.3.2) 1542 - '@typescript-eslint/visitor-keys': 8.8.1 1543 - debug: 4.3.4 1544 - eslint: 9.12.0 1545 - optionalDependencies: 1546 - typescript: 5.3.2 1547 transitivePeerDependencies: 1548 - supports-color 1549 1550 - '@typescript-eslint/scope-manager@8.8.1': 1551 dependencies: 1552 - '@typescript-eslint/types': 8.8.1 1553 - '@typescript-eslint/visitor-keys': 8.8.1 1554 1555 - '@typescript-eslint/type-utils@8.8.1(eslint@9.12.0)(typescript@5.3.2)': 1556 dependencies: 1557 - '@typescript-eslint/typescript-estree': 8.8.1(typescript@5.3.2) 1558 - '@typescript-eslint/utils': 8.8.1(eslint@9.12.0)(typescript@5.3.2) 1559 - debug: 4.3.4 1560 - ts-api-utils: 1.3.0(typescript@5.3.2) 1561 - optionalDependencies: 1562 - typescript: 5.3.2 1563 transitivePeerDependencies: 1564 - - eslint 1565 - supports-color 1566 1567 - '@typescript-eslint/types@8.8.1': {} 1568 1569 - '@typescript-eslint/typescript-estree@8.8.1(typescript@5.3.2)': 1570 dependencies: 1571 - '@typescript-eslint/types': 8.8.1 1572 - '@typescript-eslint/visitor-keys': 8.8.1 1573 - debug: 4.3.4 1574 fast-glob: 3.3.2 1575 is-glob: 4.0.3 1576 minimatch: 9.0.5 1577 - semver: 7.6.3 1578 - ts-api-utils: 1.3.0(typescript@5.3.2) 1579 - optionalDependencies: 1580 - typescript: 5.3.2 1581 transitivePeerDependencies: 1582 - supports-color 1583 1584 - '@typescript-eslint/utils@8.8.1(eslint@9.12.0)(typescript@5.3.2)': 1585 dependencies: 1586 - '@eslint-community/eslint-utils': 4.4.0(eslint@9.12.0) 1587 - '@typescript-eslint/scope-manager': 8.8.1 1588 - '@typescript-eslint/types': 8.8.1 1589 - '@typescript-eslint/typescript-estree': 8.8.1(typescript@5.3.2) 1590 - eslint: 9.12.0 1591 transitivePeerDependencies: 1592 - supports-color 1593 - - typescript 1594 1595 - '@typescript-eslint/visitor-keys@8.8.1': 1596 dependencies: 1597 - '@typescript-eslint/types': 8.8.1 1598 - eslint-visitor-keys: 3.4.3 1599 1600 - '@zenfs/core@1.0.2': 1601 dependencies: 1602 - '@types/node': 20.16.10 1603 - '@types/readable-stream': 4.0.15 1604 buffer: 6.0.3 1605 eventemitter3: 5.0.1 1606 - minimatch: 9.0.5 1607 readable-stream: 4.5.2 1608 - utilium: 0.7.1 1609 1610 - '@zenfs/dom@0.2.16(@zenfs/core@1.0.2)': 1611 dependencies: 1612 - '@zenfs/core': 1.0.2 1613 1614 abort-controller@3.0.0: 1615 dependencies: 1616 event-target-shim: 5.0.1 1617 1618 - acorn-jsx@5.3.2(acorn@8.12.1): 1619 dependencies: 1620 - acorn: 8.12.1 1621 1622 - acorn@8.12.1: {} 1623 1624 ajv@6.12.6: 1625 dependencies: ··· 1632 dependencies: 1633 color-convert: 2.0.1 1634 1635 argparse@2.0.1: {} 1636 1637 - array-buffer-byte-length@1.0.1: 1638 dependencies: 1639 - call-bind: 1.0.7 1640 - is-array-buffer: 3.0.4 1641 1642 array-includes@3.1.8: 1643 dependencies: 1644 - call-bind: 1.0.7 1645 define-properties: 1.2.1 1646 - es-abstract: 1.23.3 1647 - es-object-atoms: 1.0.0 1648 - get-intrinsic: 1.2.4 1649 - is-string: 1.0.7 1650 1651 array.prototype.findlast@1.2.5: 1652 dependencies: 1653 - call-bind: 1.0.7 1654 define-properties: 1.2.1 1655 - es-abstract: 1.23.3 1656 es-errors: 1.3.0 1657 - es-object-atoms: 1.0.0 1658 - es-shim-unscopables: 1.0.2 1659 1660 - array.prototype.flat@1.3.2: 1661 dependencies: 1662 - call-bind: 1.0.7 1663 define-properties: 1.2.1 1664 - es-abstract: 1.23.3 1665 - es-shim-unscopables: 1.0.2 1666 1667 - array.prototype.flatmap@1.3.2: 1668 dependencies: 1669 - call-bind: 1.0.7 1670 define-properties: 1.2.1 1671 - es-abstract: 1.23.3 1672 - es-shim-unscopables: 1.0.2 1673 1674 array.prototype.tosorted@1.1.4: 1675 dependencies: 1676 - call-bind: 1.0.7 1677 define-properties: 1.2.1 1678 - es-abstract: 1.23.3 1679 es-errors: 1.3.0 1680 - es-shim-unscopables: 1.0.2 1681 1682 - arraybuffer.prototype.slice@1.0.3: 1683 dependencies: 1684 - array-buffer-byte-length: 1.0.1 1685 - call-bind: 1.0.7 1686 define-properties: 1.2.1 1687 - es-abstract: 1.23.3 1688 es-errors: 1.3.0 1689 - get-intrinsic: 1.2.4 1690 - is-array-buffer: 3.0.4 1691 - is-shared-array-buffer: 1.0.3 1692 1693 astring@1.9.0: {} 1694 1695 available-typed-arrays@1.0.7: 1696 dependencies: 1697 - possible-typed-array-names: 1.0.0 1698 1699 balanced-match@1.0.2: {} 1700 ··· 1718 base64-js: 1.5.1 1719 ieee754: 1.2.1 1720 1721 - call-bind@1.0.7: 1722 dependencies: 1723 - es-define-property: 1.0.0 1724 es-errors: 1.3.0 1725 function-bind: 1.1.2 1726 - get-intrinsic: 1.2.4 1727 set-function-length: 1.2.2 1728 1729 callsites@3.1.0: {} 1730 1731 chalk@4.1.2: ··· 1741 1742 concat-map@0.0.1: {} 1743 1744 - cross-spawn@7.0.3: 1745 dependencies: 1746 path-key: 3.1.1 1747 shebang-command: 2.0.0 1748 which: 2.0.2 1749 1750 - csstype@3.1.2: {} 1751 - 1752 csstype@3.1.3: {} 1753 1754 - data-view-buffer@1.0.1: 1755 dependencies: 1756 - call-bind: 1.0.7 1757 es-errors: 1.3.0 1758 - is-data-view: 1.0.1 1759 1760 - data-view-byte-length@1.0.1: 1761 dependencies: 1762 - call-bind: 1.0.7 1763 es-errors: 1.3.0 1764 - is-data-view: 1.0.1 1765 1766 - data-view-byte-offset@1.0.0: 1767 dependencies: 1768 - call-bind: 1.0.7 1769 es-errors: 1.3.0 1770 - is-data-view: 1.0.1 1771 1772 - debug@4.3.4: 1773 dependencies: 1774 - ms: 2.1.2 1775 1776 deep-is@0.1.4: {} 1777 1778 define-data-property@1.1.4: 1779 dependencies: 1780 - es-define-property: 1.0.0 1781 es-errors: 1.3.0 1782 - gopd: 1.0.1 1783 1784 define-properties@1.2.1: 1785 dependencies: ··· 1787 has-property-descriptors: 1.0.2 1788 object-keys: 1.1.1 1789 1790 doctrine@2.1.0: 1791 dependencies: 1792 esutils: 2.0.3 1793 1794 - es-abstract@1.23.3: 1795 dependencies: 1796 - array-buffer-byte-length: 1.0.1 1797 - arraybuffer.prototype.slice: 1.0.3 1798 available-typed-arrays: 1.0.7 1799 - call-bind: 1.0.7 1800 - data-view-buffer: 1.0.1 1801 - data-view-byte-length: 1.0.1 1802 - data-view-byte-offset: 1.0.0 1803 - es-define-property: 1.0.0 1804 es-errors: 1.3.0 1805 - es-object-atoms: 1.0.0 1806 - es-set-tostringtag: 2.0.3 1807 - es-to-primitive: 1.2.1 1808 - function.prototype.name: 1.1.6 1809 - get-intrinsic: 1.2.4 1810 - get-symbol-description: 1.0.2 1811 globalthis: 1.0.4 1812 - gopd: 1.0.1 1813 has-property-descriptors: 1.0.2 1814 - has-proto: 1.0.3 1815 - has-symbols: 1.0.3 1816 hasown: 2.0.2 1817 - internal-slot: 1.0.7 1818 - is-array-buffer: 3.0.4 1819 is-callable: 1.2.7 1820 - is-data-view: 1.0.1 1821 - is-negative-zero: 2.0.3 1822 - is-regex: 1.1.4 1823 - is-shared-array-buffer: 1.0.3 1824 - is-string: 1.0.7 1825 - is-typed-array: 1.1.13 1826 - is-weakref: 1.0.2 1827 - object-inspect: 1.13.2 1828 object-keys: 1.1.1 1829 - object.assign: 4.1.5 1830 - regexp.prototype.flags: 1.5.3 1831 - safe-array-concat: 1.1.2 1832 - safe-regex-test: 1.0.3 1833 - string.prototype.trim: 1.2.9 1834 - string.prototype.trimend: 1.0.8 1835 string.prototype.trimstart: 1.0.8 1836 - typed-array-buffer: 1.0.2 1837 - typed-array-byte-length: 1.0.1 1838 - typed-array-byte-offset: 1.0.2 1839 - typed-array-length: 1.0.6 1840 - unbox-primitive: 1.0.2 1841 - which-typed-array: 1.1.15 1842 1843 - es-define-property@1.0.0: 1844 - dependencies: 1845 - get-intrinsic: 1.2.4 1846 1847 es-errors@1.3.0: {} 1848 1849 - es-iterator-helpers@1.1.0: 1850 dependencies: 1851 - call-bind: 1.0.7 1852 define-properties: 1.2.1 1853 - es-abstract: 1.23.3 1854 es-errors: 1.3.0 1855 - es-set-tostringtag: 2.0.3 1856 function-bind: 1.1.2 1857 - get-intrinsic: 1.2.4 1858 globalthis: 1.0.4 1859 has-property-descriptors: 1.0.2 1860 - has-proto: 1.0.3 1861 - has-symbols: 1.0.3 1862 - internal-slot: 1.0.7 1863 - iterator.prototype: 1.1.3 1864 - safe-array-concat: 1.1.2 1865 1866 - es-object-atoms@1.0.0: 1867 dependencies: 1868 es-errors: 1.3.0 1869 1870 - es-set-tostringtag@2.0.3: 1871 dependencies: 1872 - get-intrinsic: 1.2.4 1873 has-tostringtag: 1.0.2 1874 hasown: 2.0.2 1875 1876 - es-shim-unscopables@1.0.2: 1877 dependencies: 1878 hasown: 2.0.2 1879 1880 - es-to-primitive@1.2.1: 1881 dependencies: 1882 is-callable: 1.2.7 1883 - is-date-object: 1.0.5 1884 - is-symbol: 1.0.4 1885 1886 esbuild-copy-static-files@0.1.0: {} 1887 ··· 1912 1913 escape-string-regexp@4.0.0: {} 1914 1915 - eslint-config-prettier@9.1.0(eslint@9.12.0): 1916 dependencies: 1917 - eslint: 9.12.0 1918 1919 - eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0(eslint@9.12.0))(eslint@9.12.0)(prettier@3.1.0): 1920 dependencies: 1921 - eslint: 9.12.0 1922 prettier: 3.1.0 1923 prettier-linter-helpers: 1.0.0 1924 - synckit: 0.9.2 1925 optionalDependencies: 1926 - eslint-config-prettier: 9.1.0(eslint@9.12.0) 1927 1928 - eslint-plugin-react@7.37.1(eslint@9.12.0): 1929 dependencies: 1930 array-includes: 3.1.8 1931 array.prototype.findlast: 1.2.5 1932 - array.prototype.flatmap: 1.3.2 1933 array.prototype.tosorted: 1.1.4 1934 doctrine: 2.1.0 1935 - es-iterator-helpers: 1.1.0 1936 - eslint: 9.12.0 1937 estraverse: 5.3.0 1938 hasown: 2.0.2 1939 jsx-ast-utils: 3.3.5 1940 minimatch: 3.1.2 1941 - object.entries: 1.1.8 1942 object.fromentries: 2.0.8 1943 - object.values: 1.2.0 1944 prop-types: 15.8.1 1945 resolve: 2.0.0-next.5 1946 semver: 6.3.1 1947 - string.prototype.matchall: 4.0.11 1948 string.prototype.repeat: 1.0.0 1949 1950 - eslint-scope@8.1.0: 1951 dependencies: 1952 esrecurse: 4.3.0 1953 estraverse: 5.3.0 1954 1955 eslint-visitor-keys@3.4.3: {} 1956 1957 - eslint-visitor-keys@4.1.0: {} 1958 1959 - eslint@9.12.0: 1960 dependencies: 1961 - '@eslint-community/eslint-utils': 4.4.0(eslint@9.12.0) 1962 - '@eslint-community/regexpp': 4.11.1 1963 - '@eslint/config-array': 0.18.0 1964 - '@eslint/core': 0.6.0 1965 - '@eslint/eslintrc': 3.1.0 1966 - '@eslint/js': 9.12.0 1967 - '@eslint/plugin-kit': 0.2.0 1968 - '@humanfs/node': 0.16.5 1969 '@humanwhocodes/module-importer': 1.0.1 1970 - '@humanwhocodes/retry': 0.3.1 1971 '@types/estree': 1.0.6 1972 '@types/json-schema': 7.0.15 1973 ajv: 6.12.6 1974 chalk: 4.1.2 1975 - cross-spawn: 7.0.3 1976 - debug: 4.3.4 1977 escape-string-regexp: 4.0.0 1978 - eslint-scope: 8.1.0 1979 - eslint-visitor-keys: 4.1.0 1980 - espree: 10.2.0 1981 - esquery: 1.5.0 1982 esutils: 2.0.3 1983 fast-deep-equal: 3.1.3 1984 file-entry-cache: 8.0.0 1985 find-up: 5.0.0 1986 glob-parent: 6.0.2 1987 - ignore: 5.3.0 1988 imurmurhash: 0.1.4 1989 is-glob: 4.0.3 1990 json-stable-stringify-without-jsonify: 1.0.1 ··· 1992 minimatch: 3.1.2 1993 natural-compare: 1.4.0 1994 optionator: 0.9.3 1995 - text-table: 0.2.0 1996 transitivePeerDependencies: 1997 - supports-color 1998 1999 - espree@10.2.0: 2000 dependencies: 2001 - acorn: 8.12.1 2002 - acorn-jsx: 5.3.2(acorn@8.12.1) 2003 - eslint-visitor-keys: 4.1.0 2004 2005 - esquery@1.5.0: 2006 dependencies: 2007 estraverse: 5.3.0 2008 ··· 2045 dependencies: 2046 reusify: 1.0.4 2047 2048 file-entry-cache@8.0.0: 2049 dependencies: 2050 flat-cache: 4.0.1 ··· 2053 dependencies: 2054 to-regex-range: 5.0.1 2055 2056 find-up@5.0.0: 2057 dependencies: 2058 locate-path: 6.0.0 ··· 2065 2066 flatted@3.2.9: {} 2067 2068 - for-each@0.3.3: 2069 dependencies: 2070 is-callable: 1.2.7 2071 2072 function-bind@1.1.2: {} 2073 2074 - function.prototype.name@1.1.6: 2075 dependencies: 2076 - call-bind: 1.0.7 2077 define-properties: 1.2.1 2078 - es-abstract: 1.23.3 2079 functions-have-names: 1.2.3 2080 2081 functions-have-names@1.2.3: {} 2082 2083 - get-intrinsic@1.2.4: 2084 dependencies: 2085 es-errors: 1.3.0 2086 function-bind: 1.1.2 2087 - has-proto: 1.0.3 2088 - has-symbols: 1.0.3 2089 hasown: 2.0.2 2090 2091 - get-symbol-description@1.0.2: 2092 dependencies: 2093 - call-bind: 1.0.7 2094 es-errors: 1.3.0 2095 - get-intrinsic: 1.2.4 2096 2097 glob-parent@5.1.2: 2098 dependencies: ··· 2107 globalthis@1.0.4: 2108 dependencies: 2109 define-properties: 1.2.1 2110 - gopd: 1.0.1 2111 2112 - gopd@1.0.1: 2113 - dependencies: 2114 - get-intrinsic: 1.2.4 2115 2116 graphemer@1.4.0: {} 2117 2118 - has-bigints@1.0.2: {} 2119 2120 has-flag@4.0.0: {} 2121 2122 has-property-descriptors@1.0.2: 2123 dependencies: 2124 - es-define-property: 1.0.0 2125 2126 - has-proto@1.0.3: {} 2127 2128 - has-symbols@1.0.3: {} 2129 2130 has-tostringtag@1.0.2: 2131 dependencies: 2132 - has-symbols: 1.0.3 2133 2134 hasown@2.0.2: 2135 dependencies: ··· 2138 husky@8.0.3: {} 2139 2140 ieee754@1.2.1: {} 2141 - 2142 - ignore@5.3.0: {} 2143 2144 ignore@5.3.2: {} 2145 ··· 2150 2151 imurmurhash@0.1.4: {} 2152 2153 - internal-slot@1.0.7: 2154 dependencies: 2155 es-errors: 1.3.0 2156 hasown: 2.0.2 2157 - side-channel: 1.0.6 2158 2159 - is-array-buffer@3.0.4: 2160 dependencies: 2161 - call-bind: 1.0.7 2162 - get-intrinsic: 1.2.4 2163 2164 - is-async-function@2.0.0: 2165 dependencies: 2166 has-tostringtag: 1.0.2 2167 2168 - is-bigint@1.0.4: 2169 dependencies: 2170 - has-bigints: 1.0.2 2171 2172 - is-boolean-object@1.1.2: 2173 dependencies: 2174 - call-bind: 1.0.7 2175 has-tostringtag: 1.0.2 2176 2177 is-callable@1.2.7: {} 2178 2179 - is-core-module@2.15.1: 2180 dependencies: 2181 hasown: 2.0.2 2182 2183 - is-data-view@1.0.1: 2184 dependencies: 2185 - is-typed-array: 1.1.13 2186 2187 - is-date-object@1.0.5: 2188 dependencies: 2189 has-tostringtag: 1.0.2 2190 2191 is-extglob@2.1.1: {} 2192 2193 - is-finalizationregistry@1.0.2: 2194 dependencies: 2195 - call-bind: 1.0.7 2196 2197 - is-generator-function@1.0.10: 2198 dependencies: 2199 has-tostringtag: 1.0.2 2200 2201 is-glob@4.0.3: 2202 dependencies: ··· 2204 2205 is-map@2.0.3: {} 2206 2207 - is-negative-zero@2.0.3: {} 2208 - 2209 - is-number-object@1.0.7: 2210 dependencies: 2211 has-tostringtag: 1.0.2 2212 2213 is-number@7.0.0: {} 2214 2215 - is-regex@1.1.4: 2216 dependencies: 2217 - call-bind: 1.0.7 2218 has-tostringtag: 1.0.2 2219 2220 is-set@2.0.3: {} 2221 2222 - is-shared-array-buffer@1.0.3: 2223 dependencies: 2224 - call-bind: 1.0.7 2225 2226 - is-string@1.0.7: 2227 dependencies: 2228 has-tostringtag: 1.0.2 2229 2230 - is-symbol@1.0.4: 2231 dependencies: 2232 - has-symbols: 1.0.3 2233 2234 - is-typed-array@1.1.13: 2235 dependencies: 2236 - which-typed-array: 1.1.15 2237 2238 is-weakmap@2.0.2: {} 2239 2240 - is-weakref@1.0.2: 2241 dependencies: 2242 - call-bind: 1.0.7 2243 2244 - is-weakset@2.0.3: 2245 dependencies: 2246 - call-bind: 1.0.7 2247 - get-intrinsic: 1.2.4 2248 2249 isarray@2.0.5: {} 2250 2251 isexe@2.0.0: {} 2252 2253 - iterator.prototype@1.1.3: 2254 dependencies: 2255 - define-properties: 1.2.1 2256 - get-intrinsic: 1.2.4 2257 - has-symbols: 1.0.3 2258 - reflect.getprototypeof: 1.0.6 2259 set-function-name: 2.0.2 2260 2261 js-tokens@4.0.0: {} 2262 2263 js-yaml@4.1.0: ··· 2273 jsx-ast-utils@3.3.5: 2274 dependencies: 2275 array-includes: 3.1.8 2276 - array.prototype.flat: 1.3.2 2277 - object.assign: 4.1.5 2278 - object.values: 1.2.0 2279 2280 keyv@4.5.4: 2281 dependencies: ··· 2296 dependencies: 2297 js-tokens: 4.0.0 2298 2299 merge2@1.4.1: {} 2300 2301 meriyah@6.0.1: {} ··· 2306 dependencies: 2307 braces: 3.0.3 2308 picomatch: 2.3.1 2309 2310 minimatch@3.1.2: 2311 dependencies: ··· 2315 dependencies: 2316 brace-expansion: 2.0.1 2317 2318 - ms@2.1.2: {} 2319 2320 nanotar@0.1.1: {} 2321 2322 natural-compare@1.4.0: {} 2323 2324 object-assign@4.1.1: {} 2325 2326 - object-inspect@1.13.2: {} 2327 2328 object-keys@1.1.1: {} 2329 2330 - object.assign@4.1.5: 2331 dependencies: 2332 - call-bind: 1.0.7 2333 define-properties: 1.2.1 2334 - has-symbols: 1.0.3 2335 object-keys: 1.1.1 2336 2337 - object.entries@1.1.8: 2338 dependencies: 2339 - call-bind: 1.0.7 2340 define-properties: 1.2.1 2341 - es-object-atoms: 1.0.0 2342 2343 object.fromentries@2.0.8: 2344 dependencies: 2345 - call-bind: 1.0.7 2346 define-properties: 1.2.1 2347 - es-abstract: 1.23.3 2348 - es-object-atoms: 1.0.0 2349 2350 - object.values@1.2.0: 2351 dependencies: 2352 - call-bind: 1.0.7 2353 define-properties: 1.2.1 2354 - es-object-atoms: 1.0.0 2355 2356 optionator@0.9.3: 2357 dependencies: ··· 2361 levn: 0.4.1 2362 prelude-ls: 1.2.1 2363 type-check: 0.4.0 2364 2365 p-limit@3.1.0: 2366 dependencies: ··· 2370 dependencies: 2371 p-limit: 3.1.0 2372 2373 parent-module@1.0.1: 2374 dependencies: 2375 callsites: 3.1.0 ··· 2380 2381 path-parse@1.0.7: {} 2382 2383 picomatch@2.3.1: {} 2384 2385 - possible-typed-array-names@1.0.0: {} 2386 2387 prelude-ls@1.2.1: {} 2388 ··· 2402 2403 punycode@2.3.1: {} 2404 2405 queue-microtask@1.2.3: {} 2406 2407 react-is@16.13.1: {} ··· 2414 process: 0.11.10 2415 string_decoder: 1.3.0 2416 2417 - reflect.getprototypeof@1.0.6: 2418 dependencies: 2419 - call-bind: 1.0.7 2420 define-properties: 1.2.1 2421 - es-abstract: 1.23.3 2422 es-errors: 1.3.0 2423 - get-intrinsic: 1.2.4 2424 - globalthis: 1.0.4 2425 - which-builtin-type: 1.1.4 2426 2427 - regexp.prototype.flags@1.5.3: 2428 dependencies: 2429 - call-bind: 1.0.7 2430 define-properties: 1.2.1 2431 es-errors: 1.3.0 2432 set-function-name: 2.0.2 2433 2434 resolve-from@4.0.0: {} 2435 2436 resolve@2.0.0-next.5: 2437 dependencies: 2438 - is-core-module: 2.15.1 2439 path-parse: 1.0.7 2440 supports-preserve-symlinks-flag: 1.0.0 2441 2442 reusify@1.0.4: {} 2443 2444 run-parallel@1.2.0: 2445 dependencies: 2446 queue-microtask: 1.2.3 2447 2448 - safe-array-concat@1.1.2: 2449 dependencies: 2450 - call-bind: 1.0.7 2451 - get-intrinsic: 1.2.4 2452 - has-symbols: 1.0.3 2453 isarray: 2.0.5 2454 2455 - safe-buffer@5.1.2: {} 2456 - 2457 safe-buffer@5.2.1: {} 2458 2459 - safe-regex-test@1.0.3: 2460 dependencies: 2461 - call-bind: 1.0.7 2462 es-errors: 1.3.0 2463 - is-regex: 1.1.4 2464 2465 semver@6.3.1: {} 2466 2467 - semver@7.6.3: {} 2468 2469 set-function-length@1.2.2: 2470 dependencies: 2471 define-data-property: 1.1.4 2472 es-errors: 1.3.0 2473 function-bind: 1.1.2 2474 - get-intrinsic: 1.2.4 2475 - gopd: 1.0.1 2476 has-property-descriptors: 1.0.2 2477 2478 set-function-name@2.0.2: ··· 2482 functions-have-names: 1.2.3 2483 has-property-descriptors: 1.0.2 2484 2485 shebang-command@2.0.0: 2486 dependencies: 2487 shebang-regex: 3.0.0 2488 2489 shebang-regex@3.0.0: {} 2490 2491 - side-channel@1.0.6: 2492 dependencies: 2493 - call-bind: 1.0.7 2494 es-errors: 1.3.0 2495 - get-intrinsic: 1.2.4 2496 - object-inspect: 1.13.2 2497 2498 standalone-electron-types@1.0.0: 2499 dependencies: 2500 '@types/node': 18.17.17 2501 2502 - string.prototype.matchall@4.0.11: 2503 dependencies: 2504 - call-bind: 1.0.7 2505 define-properties: 1.2.1 2506 - es-abstract: 1.23.3 2507 es-errors: 1.3.0 2508 - es-object-atoms: 1.0.0 2509 - get-intrinsic: 1.2.4 2510 - gopd: 1.0.1 2511 - has-symbols: 1.0.3 2512 - internal-slot: 1.0.7 2513 - regexp.prototype.flags: 1.5.3 2514 set-function-name: 2.0.2 2515 - side-channel: 1.0.6 2516 2517 string.prototype.repeat@1.0.0: 2518 dependencies: 2519 define-properties: 1.2.1 2520 - es-abstract: 1.23.3 2521 2522 - string.prototype.trim@1.2.9: 2523 dependencies: 2524 - call-bind: 1.0.7 2525 define-properties: 1.2.1 2526 - es-abstract: 1.23.3 2527 - es-object-atoms: 1.0.0 2528 2529 - string.prototype.trimend@1.0.8: 2530 dependencies: 2531 - call-bind: 1.0.7 2532 define-properties: 1.2.1 2533 - es-object-atoms: 1.0.0 2534 2535 string.prototype.trimstart@1.0.8: 2536 dependencies: 2537 - call-bind: 1.0.7 2538 define-properties: 1.2.1 2539 - es-object-atoms: 1.0.0 2540 2541 string_decoder@1.3.0: 2542 dependencies: ··· 2550 2551 supports-preserve-symlinks-flag@1.0.0: {} 2552 2553 - synckit@0.9.2: 2554 dependencies: 2555 - '@pkgr/core': 0.1.1 2556 - tslib: 2.7.0 2557 2558 - text-table@0.2.0: {} 2559 2560 to-regex-range@5.0.1: 2561 dependencies: 2562 is-number: 7.0.0 2563 2564 - ts-api-utils@1.3.0(typescript@5.3.2): 2565 dependencies: 2566 - typescript: 5.3.2 2567 2568 - tslib@2.7.0: {} 2569 2570 type-check@0.4.0: 2571 dependencies: 2572 prelude-ls: 1.2.1 2573 2574 - typed-array-buffer@1.0.2: 2575 dependencies: 2576 - call-bind: 1.0.7 2577 es-errors: 1.3.0 2578 - is-typed-array: 1.1.13 2579 2580 - typed-array-byte-length@1.0.1: 2581 dependencies: 2582 - call-bind: 1.0.7 2583 - for-each: 0.3.3 2584 - gopd: 1.0.1 2585 - has-proto: 1.0.3 2586 - is-typed-array: 1.1.13 2587 2588 - typed-array-byte-offset@1.0.2: 2589 dependencies: 2590 available-typed-arrays: 1.0.7 2591 - call-bind: 1.0.7 2592 - for-each: 0.3.3 2593 - gopd: 1.0.1 2594 - has-proto: 1.0.3 2595 - is-typed-array: 1.1.13 2596 2597 - typed-array-length@1.0.6: 2598 dependencies: 2599 - call-bind: 1.0.7 2600 - for-each: 0.3.3 2601 - gopd: 1.0.1 2602 - has-proto: 1.0.3 2603 - is-typed-array: 1.1.13 2604 - possible-typed-array-names: 1.0.0 2605 2606 - typescript-eslint@8.8.1(eslint@9.12.0)(typescript@5.3.2): 2607 dependencies: 2608 - '@typescript-eslint/eslint-plugin': 8.8.1(@typescript-eslint/parser@8.8.1(eslint@9.12.0)(typescript@5.3.2))(eslint@9.12.0)(typescript@5.3.2) 2609 - '@typescript-eslint/parser': 8.8.1(eslint@9.12.0)(typescript@5.3.2) 2610 - '@typescript-eslint/utils': 8.8.1(eslint@9.12.0)(typescript@5.3.2) 2611 - optionalDependencies: 2612 - typescript: 5.3.2 2613 transitivePeerDependencies: 2614 - - eslint 2615 - supports-color 2616 2617 - typescript@5.3.2: {} 2618 2619 - unbox-primitive@1.0.2: 2620 dependencies: 2621 - call-bind: 1.0.7 2622 - has-bigints: 1.0.2 2623 - has-symbols: 1.0.3 2624 - which-boxed-primitive: 1.0.2 2625 2626 - undici-types@6.19.8: {} 2627 2628 uri-js@4.4.1: 2629 dependencies: 2630 punycode: 2.3.1 2631 2632 - utilium@0.7.1: 2633 dependencies: 2634 eventemitter3: 5.0.1 2635 2636 - which-boxed-primitive@1.0.2: 2637 dependencies: 2638 - is-bigint: 1.0.4 2639 - is-boolean-object: 1.1.2 2640 - is-number-object: 1.0.7 2641 - is-string: 1.0.7 2642 - is-symbol: 1.0.4 2643 2644 - which-builtin-type@1.1.4: 2645 dependencies: 2646 - function.prototype.name: 1.1.6 2647 has-tostringtag: 1.0.2 2648 - is-async-function: 2.0.0 2649 - is-date-object: 1.0.5 2650 - is-finalizationregistry: 1.0.2 2651 - is-generator-function: 1.0.10 2652 - is-regex: 1.1.4 2653 - is-weakref: 1.0.2 2654 isarray: 2.0.5 2655 - which-boxed-primitive: 1.0.2 2656 which-collection: 1.0.2 2657 - which-typed-array: 1.1.15 2658 2659 which-collection@1.0.2: 2660 dependencies: 2661 is-map: 2.0.3 2662 is-set: 2.0.3 2663 is-weakmap: 2.0.2 2664 - is-weakset: 2.0.3 2665 2666 - which-typed-array@1.1.15: 2667 dependencies: 2668 available-typed-arrays: 1.0.7 2669 - call-bind: 1.0.7 2670 - for-each: 0.3.3 2671 - gopd: 1.0.1 2672 has-tostringtag: 1.0.2 2673 2674 which@2.0.2: 2675 dependencies: 2676 isexe: 2.0.0 2677 2678 yocto-queue@0.1.0: {}
··· 4 autoInstallPeers: true 5 excludeLinksFromLockfile: false 6 7 + catalogs: 8 + dev: 9 + '@moonlight-mod/eslint-config': 10 + specifier: github:moonlight-mod/eslint-config 11 + version: 1.0.1 12 + '@types/chrome': 13 + specifier: ^0.0.313 14 + version: 0.0.313 15 + '@types/node': 16 + specifier: ^22.14.0 17 + version: 22.14.0 18 + esbuild: 19 + specifier: ^0.19.3 20 + version: 0.19.3 21 + esbuild-copy-static-files: 22 + specifier: ^0.1.0 23 + version: 0.1.0 24 + eslint: 25 + specifier: ^9.12.0 26 + version: 9.23.0 27 + husky: 28 + specifier: ^8.0.3 29 + version: 8.0.3 30 + prettier: 31 + specifier: ^3.1.0 32 + version: 3.1.0 33 + taze: 34 + specifier: ^19.0.4 35 + version: 19.0.4 36 + typescript: 37 + specifier: ^5.3.3 38 + version: 5.8.2 39 + prod: 40 + '@moonlight-mod/lunast': 41 + specifier: ^1.0.1 42 + version: 1.0.1 43 + '@moonlight-mod/mappings': 44 + specifier: ^1.1.25 45 + version: 1.1.25 46 + '@moonlight-mod/moonmap': 47 + specifier: ^1.0.5 48 + version: 1.0.5 49 + '@zenfs/core': 50 + specifier: ^2.0.0 51 + version: 2.0.0 52 + '@zenfs/dom': 53 + specifier: ^1.1.3 54 + version: 1.1.6 55 + microdiff: 56 + specifier: ^1.5.0 57 + version: 1.5.0 58 + nanotar: 59 + specifier: ^0.1.1 60 + version: 0.1.1 61 + 62 importers: 63 64 .: 65 devDependencies: 66 '@moonlight-mod/eslint-config': 67 + specifier: catalog:dev 68 + version: https://codeload.github.com/moonlight-mod/eslint-config/tar.gz/e262ac24e1a0955a9b3e0d66da247a0a8c0446c9(@types/eslint@9.6.1)(eslint@9.23.0(jiti@2.4.2))(prettier@3.1.0)(typescript@5.8.2) 69 + '@types/node': 70 + specifier: catalog:dev 71 + version: 22.14.0 72 esbuild: 73 + specifier: catalog:dev 74 version: 0.19.3 75 esbuild-copy-static-files: 76 + specifier: catalog:dev 77 version: 0.1.0 78 eslint: 79 + specifier: catalog:dev 80 + version: 9.23.0(jiti@2.4.2) 81 husky: 82 + specifier: catalog:dev 83 version: 8.0.3 84 prettier: 85 + specifier: catalog:dev 86 version: 3.1.0 87 + taze: 88 + specifier: catalog:dev 89 + version: 19.0.4 90 typescript: 91 + specifier: catalog:dev 92 + version: 5.8.2 93 94 packages/browser: 95 dependencies: ··· 103 specifier: workspace:* 104 version: link:../web-preload 105 '@zenfs/core': 106 + specifier: catalog:prod 107 + version: 2.0.0 108 '@zenfs/dom': 109 + specifier: catalog:prod 110 + version: 1.1.6(@zenfs/core@2.0.0)(utilium@1.10.1) 111 + devDependencies: 112 + '@types/chrome': 113 + specifier: catalog:dev 114 + version: 0.0.313 115 116 packages/core: 117 dependencies: ··· 128 specifier: workspace:* 129 version: link:../types 130 microdiff: 131 + specifier: catalog:prod 132 version: 1.5.0 133 nanotar: 134 + specifier: catalog:prod 135 version: 0.1.1 136 137 packages/injector: ··· 155 packages/types: 156 dependencies: 157 '@moonlight-mod/lunast': 158 + specifier: ^1.0.1 159 + version: 1.0.1 160 '@moonlight-mod/mappings': 161 + specifier: ^1.1.25 162 + version: 1.1.25(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5) 163 '@moonlight-mod/moonmap': 164 + specifier: ^1.0.5 165 + version: 1.0.5 166 '@types/react': 167 specifier: ^18.3.10 168 + version: 18.3.20 169 csstype: 170 + specifier: ^3.1.3 171 + version: 3.1.3 172 standalone-electron-types: 173 specifier: ^1.0.0 174 version: 1.0.0 ··· 179 specifier: workspace:* 180 version: link:../core 181 '@moonlight-mod/lunast': 182 + specifier: catalog:prod 183 + version: 1.0.1 184 '@moonlight-mod/mappings': 185 + specifier: catalog:prod 186 + version: 1.1.25(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5) 187 '@moonlight-mod/moonmap': 188 + specifier: catalog:prod 189 + version: 1.0.5 190 '@moonlight-mod/types': 191 specifier: workspace:* 192 version: link:../types ··· 196 '@aashutoshrathi/word-wrap@1.2.6': 197 resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} 198 engines: {node: '>=0.10.0'} 199 + 200 + '@antfu/ni@24.3.0': 201 + resolution: {integrity: sha512-wBSav4mBxvHEW9RbdSo1SWLQ6MAlT0Dc423weC58yOWqW4OcMvtnNDdDrxOZeJ88fEIyPK93gDUWIelBxzSf8g==} 202 + hasBin: true 203 204 '@esbuild/android-arm64@0.19.3': 205 resolution: {integrity: sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==} ··· 333 cpu: [x64] 334 os: [win32] 335 336 + '@eslint-community/eslint-utils@4.5.1': 337 + resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} 338 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 339 peerDependencies: 340 eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 341 342 + '@eslint-community/regexpp@4.12.1': 343 + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} 344 engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 345 346 + '@eslint/config-array@0.19.2': 347 + resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} 348 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 349 350 + '@eslint/config-helpers@0.2.1': 351 + resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} 352 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 353 354 + '@eslint/core@0.12.0': 355 + resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} 356 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 357 + 358 + '@eslint/core@0.13.0': 359 + resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} 360 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 361 + 362 + '@eslint/eslintrc@3.3.1': 363 + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} 364 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 365 366 + '@eslint/js@9.23.0': 367 + resolution: {integrity: sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==} 368 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 369 370 + '@eslint/object-schema@2.1.6': 371 + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} 372 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 373 374 + '@eslint/plugin-kit@0.2.8': 375 + resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} 376 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 377 378 + '@humanfs/core@0.19.1': 379 + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} 380 engines: {node: '>=18.18.0'} 381 382 + '@humanfs/node@0.16.6': 383 + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} 384 engines: {node: '>=18.18.0'} 385 386 '@humanwhocodes/module-importer@1.0.1': ··· 391 resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} 392 engines: {node: '>=18.18'} 393 394 + '@humanwhocodes/retry@0.4.2': 395 + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} 396 + engines: {node: '>=18.18'} 397 + 398 '@moonlight-mod/eslint-config@https://codeload.github.com/moonlight-mod/eslint-config/tar.gz/e262ac24e1a0955a9b3e0d66da247a0a8c0446c9': 399 resolution: {tarball: https://codeload.github.com/moonlight-mod/eslint-config/tar.gz/e262ac24e1a0955a9b3e0d66da247a0a8c0446c9} 400 version: 1.0.1 ··· 402 eslint: '>= 9' 403 typescript: '>= 5.3' 404 405 + '@moonlight-mod/lunast@1.0.1': 406 + resolution: {integrity: sha512-K3vxzDlfFuYKjciIW2FMlcZ1qrrkAGDGpSBlNqYGtJ0sMt9bRCd2lpSpg6AX/giSljDtmAUXa/5mOfUoDQxjBA==} 407 408 + '@moonlight-mod/mappings@1.1.25': 409 + resolution: {integrity: sha512-bgnSN9H/IBdMGxGev6RQKXuzhQxwo1090NhIDHnflguZnjiu2pg/usPfh76bqyhxRuX4SS7tiZSNTwBoSflCLg==} 410 + engines: {node: '>=22', npm: pnpm, pnpm: '>=10', yarn: pnpm} 411 peerDependencies: 412 + '@moonlight-mod/lunast': ^1.0.1 413 + '@moonlight-mod/moonmap': ^1.0.5 414 415 + '@moonlight-mod/moonmap@1.0.5': 416 + resolution: {integrity: sha512-Fdpxj8ghdulKB6TlTnchlCPey2YUKgEf1chuO1ofOIcvlqnVPBcQwSf2S80naOUQpXCDo4dQ+LWSE2fmhdDiiw==} 417 418 '@nodelib/fs.scandir@2.1.5': 419 resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} ··· 427 resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 428 engines: {node: '>= 8'} 429 430 + '@pkgr/core@0.2.0': 431 + resolution: {integrity: sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==} 432 engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} 433 + 434 + '@quansync/fs@0.1.2': 435 + resolution: {integrity: sha512-ezIadUb1aFhwJLd++WVqVpi9rnlX8vnd4ju7saPhwLHJN1mJgOv0puePTGV+FbtSnWtwoHDT8lAm4kagDZmpCg==} 436 + engines: {node: '>=20.0.0'} 437 + 438 + '@types/chroma-js@3.1.0': 439 + resolution: {integrity: sha512-Uwl3SOtUkbQ6Ye6ZYu4q4xdLGBzmY839sEHYtOT7i691neeyd+7fXWT5VIkcUSfNwIFrIjQutNYQn9h4q5HFvg==} 440 + 441 + '@types/chrome@0.0.313': 442 + resolution: {integrity: sha512-9R5T7gTaYZhkxlu+Ho4wk9FL+y/werWQY2yjGWSqCuiTsqS7nL/BE5UMTP6rU7J+oIG2FRKqrEycHhJATeltVA==} 443 + 444 + '@types/eslint@9.6.1': 445 + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} 446 447 '@types/estree-jsx@1.0.5': 448 resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} ··· 450 '@types/estree@1.0.6': 451 resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 452 453 + '@types/estree@1.0.7': 454 + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} 455 + 456 '@types/fbemitter@2.0.35': 457 resolution: {integrity: sha512-Xem6d7qUfmouCHntCrRYgDBwbf+WWRd6G+7WEFlEZFZ67LZXiYRvT2LV8wcZa6mIaAil95+ABQdKgB6hPIsnng==} 458 459 + '@types/filesystem@0.0.36': 460 + resolution: {integrity: sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==} 461 + 462 + '@types/filewriter@0.0.33': 463 + resolution: {integrity: sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==} 464 + 465 '@types/flux@3.1.14': 466 resolution: {integrity: sha512-WRXN0kQPCnqxN0/PgNgc7WBF6c8rbSHsEep3/qBLpsQ824RONdOmTs0TV7XhIW2GDNRAHO2CqCgAFLR5PChosw==} 467 + 468 + '@types/har-format@1.2.16': 469 + resolution: {integrity: sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==} 470 + 471 + '@types/highlightjs@9.12.6': 472 + resolution: {integrity: sha512-Qfd1DUrwE851Hc3tExADJY4qY8yeZMt06Xw9AJm/UtpneepJS3MZY29c33BY0wP899veaaHD4gZzYiSuQm84Fg==} 473 474 '@types/json-schema@7.0.15': 475 resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 476 477 + '@types/lodash@4.17.14': 478 + resolution: {integrity: sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==} 479 + 480 '@types/node@18.17.17': 481 resolution: {integrity: sha512-cOxcXsQ2sxiwkykdJqvyFS+MLQPLvIdwh5l6gNg8qF6s+C7XSkEWOZjK+XhUZd+mYvHV/180g2cnCcIl4l06Pw==} 482 483 + '@types/node@22.13.6': 484 + resolution: {integrity: sha512-GYmF65GI7417CpZXsEXMjT8goQQDnpRnJnDw6jIYa+le3V/lMazPZ4vZmK1B/9R17fh2VLr2zuy9d/h5xgrLAg==} 485 + 486 + '@types/node@22.14.0': 487 + resolution: {integrity: sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==} 488 + 489 + '@types/platform@1.3.6': 490 + resolution: {integrity: sha512-ZmSaqHuvzv+jC232cFoz2QqPUkaj6EvMmCrWcx3WRr7xTPVFCMUOTcOq8m2d+Zw1iKRc1kDiaA+jtNrV0hkVew==} 491 492 '@types/prop-types@15.7.13': 493 resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} 494 495 + '@types/react@18.3.20': 496 + resolution: {integrity: sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==} 497 498 + '@typescript-eslint/eslint-plugin@8.29.0': 499 + resolution: {integrity: sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==} 500 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 501 peerDependencies: 502 '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 503 eslint: ^8.57.0 || ^9.0.0 504 + typescript: '>=4.8.4 <5.9.0' 505 506 + '@typescript-eslint/parser@8.29.0': 507 + resolution: {integrity: sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==} 508 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 509 peerDependencies: 510 eslint: ^8.57.0 || ^9.0.0 511 + typescript: '>=4.8.4 <5.9.0' 512 513 + '@typescript-eslint/scope-manager@8.29.0': 514 + resolution: {integrity: sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==} 515 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 516 517 + '@typescript-eslint/type-utils@8.29.0': 518 + resolution: {integrity: sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==} 519 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 520 peerDependencies: 521 + eslint: ^8.57.0 || ^9.0.0 522 + typescript: '>=4.8.4 <5.9.0' 523 524 + '@typescript-eslint/types@8.29.0': 525 + resolution: {integrity: sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==} 526 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 527 528 + '@typescript-eslint/typescript-estree@8.29.0': 529 + resolution: {integrity: sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==} 530 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 531 peerDependencies: 532 + typescript: '>=4.8.4 <5.9.0' 533 534 + '@typescript-eslint/utils@8.29.0': 535 + resolution: {integrity: sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==} 536 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 537 peerDependencies: 538 eslint: ^8.57.0 || ^9.0.0 539 + typescript: '>=4.8.4 <5.9.0' 540 541 + '@typescript-eslint/visitor-keys@8.29.0': 542 + resolution: {integrity: sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==} 543 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 544 545 + '@xterm/xterm@5.5.0': 546 + resolution: {integrity: sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==} 547 + 548 + '@zenfs/core@2.0.0': 549 + resolution: {integrity: sha512-wOKNFTY1DJ1vdLqKdU7M8cRh0nVYZcDVu7WHuk/3u49hrSwTZVm4PzGxJUjFd8O9Wi3U5nYTbZoN7RX5mS2ldA==} 550 + engines: {node: '>= 18'} 551 hasBin: true 552 553 + '@zenfs/dom@1.1.6': 554 + resolution: {integrity: sha512-7SBTWgA0esuEv/TE+N/xk6W/XJf8uBF+LhlPNHQdXds0H7aOy/UYsWv/8glvARe+meDMMidoeWFLzUWoMXfjlA==} 555 engines: {node: '>= 18'} 556 peerDependencies: 557 + '@zenfs/core': ^2.0.0 558 + utilium: ^1.9.0 559 560 abort-controller@3.0.0: 561 resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} ··· 566 peerDependencies: 567 acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 568 569 + acorn@8.14.1: 570 + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} 571 engines: {node: '>=0.4.0'} 572 hasBin: true 573 ··· 578 resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 579 engines: {node: '>=8'} 580 581 + ansis@3.17.0: 582 + resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==} 583 + engines: {node: '>=14'} 584 + 585 argparse@2.0.1: 586 resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 587 588 + array-buffer-byte-length@1.0.2: 589 + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} 590 engines: {node: '>= 0.4'} 591 592 array-includes@3.1.8: ··· 597 resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} 598 engines: {node: '>= 0.4'} 599 600 + array.prototype.flat@1.3.3: 601 + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} 602 engines: {node: '>= 0.4'} 603 604 + array.prototype.flatmap@1.3.3: 605 + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} 606 engines: {node: '>= 0.4'} 607 608 array.prototype.tosorted@1.1.4: 609 resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} 610 engines: {node: '>= 0.4'} 611 612 + arraybuffer.prototype.slice@1.0.4: 613 + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} 614 engines: {node: '>= 0.4'} 615 616 astring@1.9.0: 617 resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} 618 hasBin: true 619 + 620 + async-function@1.0.0: 621 + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} 622 + engines: {node: '>= 0.4'} 623 624 available-typed-arrays@1.0.7: 625 resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} ··· 644 buffer@6.0.3: 645 resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} 646 647 + cac@6.7.14: 648 + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 649 + engines: {node: '>=8'} 650 + 651 + call-bind-apply-helpers@1.0.2: 652 + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} 653 + engines: {node: '>= 0.4'} 654 + 655 + call-bind@1.0.8: 656 + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} 657 + engines: {node: '>= 0.4'} 658 + 659 + call-bound@1.0.4: 660 + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} 661 engines: {node: '>= 0.4'} 662 663 callsites@3.1.0: ··· 678 concat-map@0.0.1: 679 resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 680 681 + cross-spawn@7.0.6: 682 + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 683 engines: {node: '>= 8'} 684 685 csstype@3.1.3: 686 resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 687 688 + data-view-buffer@1.0.2: 689 + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} 690 engines: {node: '>= 0.4'} 691 692 + data-view-byte-length@1.0.2: 693 + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} 694 engines: {node: '>= 0.4'} 695 696 + data-view-byte-offset@1.0.1: 697 + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} 698 engines: {node: '>= 0.4'} 699 700 + debug@4.4.0: 701 + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} 702 engines: {node: '>=6.0'} 703 peerDependencies: 704 supports-color: '*' ··· 717 resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} 718 engines: {node: '>= 0.4'} 719 720 + defu@6.1.4: 721 + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} 722 + 723 + destr@2.0.4: 724 + resolution: {integrity: sha512-FCAorltMy7QwX0QU38jOkhrv20LBpsHA8ogzvMhhPHCCKVCaN6GxrB0GGaWEWBUYI4eEjjfJ95RdP6dk9IdMQA==} 725 + 726 doctrine@2.1.0: 727 resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} 728 engines: {node: '>=0.10.0'} 729 730 + dunder-proto@1.0.1: 731 + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} 732 engines: {node: '>= 0.4'} 733 734 + es-abstract@1.23.9: 735 + resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} 736 + engines: {node: '>= 0.4'} 737 + 738 + es-define-property@1.0.1: 739 + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} 740 engines: {node: '>= 0.4'} 741 742 es-errors@1.3.0: 743 resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} 744 engines: {node: '>= 0.4'} 745 746 + es-iterator-helpers@1.2.1: 747 + resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} 748 engines: {node: '>= 0.4'} 749 750 + es-object-atoms@1.1.1: 751 + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} 752 engines: {node: '>= 0.4'} 753 754 + es-set-tostringtag@2.1.0: 755 + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} 756 engines: {node: '>= 0.4'} 757 758 + es-shim-unscopables@1.1.0: 759 + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} 760 + engines: {node: '>= 0.4'} 761 762 + es-to-primitive@1.3.0: 763 + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} 764 engines: {node: '>= 0.4'} 765 766 esbuild-copy-static-files@0.1.0: ··· 781 peerDependencies: 782 eslint: '>=7.0.0' 783 784 + eslint-plugin-prettier@5.2.6: 785 + resolution: {integrity: sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==} 786 engines: {node: ^14.18.0 || >=16.0.0} 787 peerDependencies: 788 '@types/eslint': '>=8.0.0' 789 eslint: '>=8.0.0' 790 + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' 791 prettier: '>=3.0.0' 792 peerDependenciesMeta: 793 '@types/eslint': ··· 795 eslint-config-prettier: 796 optional: true 797 798 + eslint-plugin-react@7.37.5: 799 + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} 800 engines: {node: '>=4'} 801 peerDependencies: 802 eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 803 804 + eslint-scope@8.3.0: 805 + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} 806 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 807 808 eslint-visitor-keys@3.4.3: 809 resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 810 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 811 812 + eslint-visitor-keys@4.2.0: 813 + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} 814 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 815 816 + eslint@9.23.0: 817 + resolution: {integrity: sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==} 818 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 819 hasBin: true 820 peerDependencies: ··· 823 jiti: 824 optional: true 825 826 + espree@10.3.0: 827 + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} 828 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 829 830 + esquery@1.6.0: 831 + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} 832 engines: {node: '>=0.10'} 833 834 esrecurse@4.3.0: ··· 876 fastq@1.17.1: 877 resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} 878 879 + fdir@6.4.3: 880 + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} 881 + peerDependencies: 882 + picomatch: ^3 || ^4 883 + peerDependenciesMeta: 884 + picomatch: 885 + optional: true 886 + 887 file-entry-cache@8.0.0: 888 resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} 889 engines: {node: '>=16.0.0'} ··· 892 resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 893 engines: {node: '>=8'} 894 895 + find-up-simple@1.0.1: 896 + resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} 897 + engines: {node: '>=18'} 898 + 899 find-up@5.0.0: 900 resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 901 engines: {node: '>=10'} ··· 907 flatted@3.2.9: 908 resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} 909 910 + for-each@0.3.5: 911 + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} 912 + engines: {node: '>= 0.4'} 913 914 function-bind@1.1.2: 915 resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 916 917 + function.prototype.name@1.1.8: 918 + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} 919 engines: {node: '>= 0.4'} 920 921 functions-have-names@1.2.3: 922 resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} 923 924 + fzf@0.5.2: 925 + resolution: {integrity: sha512-Tt4kuxLXFKHy8KT40zwsUPUkg1CrsgY25FxA2U/j/0WgEDCk3ddc/zLTCCcbSHX9FcKtLuVaDGtGE/STWC+j3Q==} 926 + 927 + get-intrinsic@1.3.0: 928 + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} 929 engines: {node: '>= 0.4'} 930 931 + get-proto@1.0.1: 932 + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} 933 + engines: {node: '>= 0.4'} 934 + 935 + get-symbol-description@1.1.0: 936 + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} 937 engines: {node: '>= 0.4'} 938 939 glob-parent@5.1.2: ··· 952 resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} 953 engines: {node: '>= 0.4'} 954 955 + gopd@1.2.0: 956 + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} 957 + engines: {node: '>= 0.4'} 958 959 graphemer@1.4.0: 960 resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 961 962 + has-bigints@1.1.0: 963 + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} 964 + engines: {node: '>= 0.4'} 965 966 has-flag@4.0.0: 967 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} ··· 970 has-property-descriptors@1.0.2: 971 resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} 972 973 + has-proto@1.2.0: 974 + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} 975 engines: {node: '>= 0.4'} 976 977 + has-symbols@1.1.0: 978 + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} 979 engines: {node: '>= 0.4'} 980 981 has-tostringtag@1.0.2: ··· 994 ieee754@1.2.1: 995 resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 996 997 ignore@5.3.2: 998 resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 999 engines: {node: '>= 4'} ··· 1006 resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 1007 engines: {node: '>=0.8.19'} 1008 1009 + internal-slot@1.1.0: 1010 + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} 1011 engines: {node: '>= 0.4'} 1012 1013 + is-array-buffer@3.0.5: 1014 + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} 1015 engines: {node: '>= 0.4'} 1016 1017 + is-async-function@2.1.1: 1018 + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} 1019 engines: {node: '>= 0.4'} 1020 1021 + is-bigint@1.1.0: 1022 + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} 1023 + engines: {node: '>= 0.4'} 1024 1025 + is-boolean-object@1.2.2: 1026 + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} 1027 engines: {node: '>= 0.4'} 1028 1029 is-callable@1.2.7: 1030 resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} 1031 engines: {node: '>= 0.4'} 1032 1033 + is-core-module@2.16.1: 1034 + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} 1035 engines: {node: '>= 0.4'} 1036 1037 + is-data-view@1.0.2: 1038 + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} 1039 engines: {node: '>= 0.4'} 1040 1041 + is-date-object@1.1.0: 1042 + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} 1043 engines: {node: '>= 0.4'} 1044 1045 is-extglob@2.1.1: 1046 resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1047 engines: {node: '>=0.10.0'} 1048 1049 + is-finalizationregistry@1.1.1: 1050 + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} 1051 + engines: {node: '>= 0.4'} 1052 1053 + is-generator-function@1.1.0: 1054 + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} 1055 engines: {node: '>= 0.4'} 1056 1057 is-glob@4.0.3: ··· 1062 resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} 1063 engines: {node: '>= 0.4'} 1064 1065 + is-number-object@1.1.1: 1066 + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} 1067 engines: {node: '>= 0.4'} 1068 1069 is-number@7.0.0: 1070 resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1071 engines: {node: '>=0.12.0'} 1072 1073 + is-regex@1.2.1: 1074 + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} 1075 engines: {node: '>= 0.4'} 1076 1077 is-set@2.0.3: 1078 resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} 1079 engines: {node: '>= 0.4'} 1080 1081 + is-shared-array-buffer@1.0.4: 1082 + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} 1083 engines: {node: '>= 0.4'} 1084 1085 + is-string@1.1.1: 1086 + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} 1087 engines: {node: '>= 0.4'} 1088 1089 + is-symbol@1.1.1: 1090 + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} 1091 engines: {node: '>= 0.4'} 1092 1093 + is-typed-array@1.1.15: 1094 + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} 1095 engines: {node: '>= 0.4'} 1096 1097 is-weakmap@2.0.2: 1098 resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} 1099 engines: {node: '>= 0.4'} 1100 1101 + is-weakref@1.1.1: 1102 + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} 1103 + engines: {node: '>= 0.4'} 1104 1105 + is-weakset@2.0.4: 1106 + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} 1107 engines: {node: '>= 0.4'} 1108 1109 isarray@2.0.5: ··· 1112 isexe@2.0.0: 1113 resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1114 1115 + iterator.prototype@1.1.5: 1116 + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} 1117 engines: {node: '>= 0.4'} 1118 1119 + jiti@2.4.2: 1120 + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} 1121 + hasBin: true 1122 + 1123 js-tokens@4.0.0: 1124 resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 1125 ··· 1158 resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 1159 hasBin: true 1160 1161 + math-intrinsics@1.1.0: 1162 + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} 1163 + engines: {node: '>= 0.4'} 1164 + 1165 merge2@1.4.1: 1166 resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1167 engines: {node: '>= 8'} ··· 1177 resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1178 engines: {node: '>=8.6'} 1179 1180 + mimic-function@5.0.1: 1181 + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} 1182 + engines: {node: '>=18'} 1183 + 1184 minimatch@3.1.2: 1185 resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1186 ··· 1188 resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1189 engines: {node: '>=16 || 14 >=14.17'} 1190 1191 + ms@2.1.3: 1192 + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1193 1194 nanotar@0.1.1: 1195 resolution: {integrity: sha512-AiJsGsSF3O0havL1BydvI4+wR76sKT+okKRwWIaK96cZUnXqH0uNBOsHlbwZq3+m2BR1VKqHDVudl3gO4mYjpQ==} ··· 1197 natural-compare@1.4.0: 1198 resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1199 1200 + node-fetch-native@1.6.6: 1201 + resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} 1202 + 1203 object-assign@4.1.1: 1204 resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1205 engines: {node: '>=0.10.0'} 1206 1207 + object-inspect@1.13.4: 1208 + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} 1209 engines: {node: '>= 0.4'} 1210 1211 object-keys@1.1.1: 1212 resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} 1213 engines: {node: '>= 0.4'} 1214 1215 + object.assign@4.1.7: 1216 + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} 1217 engines: {node: '>= 0.4'} 1218 1219 + object.entries@1.1.9: 1220 + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} 1221 engines: {node: '>= 0.4'} 1222 1223 object.fromentries@2.0.8: 1224 resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} 1225 engines: {node: '>= 0.4'} 1226 1227 + object.values@1.2.1: 1228 + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} 1229 engines: {node: '>= 0.4'} 1230 + 1231 + ofetch@1.4.1: 1232 + resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} 1233 + 1234 + onetime@7.0.0: 1235 + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} 1236 + engines: {node: '>=18'} 1237 1238 optionator@0.9.3: 1239 resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} 1240 engines: {node: '>= 0.8.0'} 1241 1242 + own-keys@1.0.1: 1243 + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} 1244 + engines: {node: '>= 0.4'} 1245 + 1246 p-limit@3.1.0: 1247 resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1248 engines: {node: '>=10'} ··· 1250 p-locate@5.0.0: 1251 resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1252 engines: {node: '>=10'} 1253 + 1254 + package-manager-detector@1.1.0: 1255 + resolution: {integrity: sha512-Y8f9qUlBzW8qauJjd/eu6jlpJZsuPJm2ZAV0cDVd420o4EdpH5RPdoCv+60/TdJflGatr4sDfpAL6ArWZbM5tA==} 1256 1257 parent-module@1.0.1: 1258 resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} ··· 1269 path-parse@1.0.7: 1270 resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1271 1272 + pathe@2.0.3: 1273 + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} 1274 + 1275 picomatch@2.3.1: 1276 resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1277 engines: {node: '>=8.6'} 1278 1279 + picomatch@4.0.2: 1280 + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} 1281 + engines: {node: '>=12'} 1282 + 1283 + pnpm-workspace-yaml@0.3.1: 1284 + resolution: {integrity: sha512-3nW5RLmREmZ8Pm8MbPsO2RM+99RRjYd25ynj3NV0cFsN7CcEl4sDFzgoFmSyduFwxFQ2Qbu3y2UdCh6HlyUOeA==} 1285 + 1286 + possible-typed-array-names@1.1.0: 1287 + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} 1288 engines: {node: '>= 0.4'} 1289 1290 prelude-ls@1.2.1: ··· 1311 resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1312 engines: {node: '>=6'} 1313 1314 + quansync@0.2.10: 1315 + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} 1316 + 1317 queue-microtask@1.2.3: 1318 resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1319 ··· 1324 resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} 1325 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1326 1327 + reflect.getprototypeof@1.0.10: 1328 + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} 1329 engines: {node: '>= 0.4'} 1330 1331 + regexp.prototype.flags@1.5.4: 1332 + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} 1333 engines: {node: '>= 0.4'} 1334 1335 resolve-from@4.0.0: ··· 1340 resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} 1341 hasBin: true 1342 1343 + restore-cursor@5.1.0: 1344 + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} 1345 + engines: {node: '>=18'} 1346 + 1347 reusify@1.0.4: 1348 resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1349 engines: {iojs: '>=1.0.0', node: '>=0.10.0'} ··· 1351 run-parallel@1.2.0: 1352 resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1353 1354 + safe-array-concat@1.1.3: 1355 + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} 1356 engines: {node: '>=0.4'} 1357 1358 safe-buffer@5.2.1: 1359 resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1360 1361 + safe-push-apply@1.0.0: 1362 + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} 1363 + engines: {node: '>= 0.4'} 1364 + 1365 + safe-regex-test@1.1.0: 1366 + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} 1367 engines: {node: '>= 0.4'} 1368 1369 semver@6.3.1: 1370 resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 1371 hasBin: true 1372 1373 + semver@7.7.1: 1374 + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} 1375 engines: {node: '>=10'} 1376 hasBin: true 1377 ··· 1383 resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} 1384 engines: {node: '>= 0.4'} 1385 1386 + set-proto@1.0.0: 1387 + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} 1388 + engines: {node: '>= 0.4'} 1389 + 1390 shebang-command@2.0.0: 1391 resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1392 engines: {node: '>=8'} ··· 1395 resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1396 engines: {node: '>=8'} 1397 1398 + side-channel-list@1.0.0: 1399 + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} 1400 + engines: {node: '>= 0.4'} 1401 + 1402 + side-channel-map@1.0.1: 1403 + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} 1404 + engines: {node: '>= 0.4'} 1405 + 1406 + side-channel-weakmap@1.0.2: 1407 + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} 1408 engines: {node: '>= 0.4'} 1409 1410 + side-channel@1.1.0: 1411 + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} 1412 + engines: {node: '>= 0.4'} 1413 + 1414 + signal-exit@4.1.0: 1415 + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1416 + engines: {node: '>=14'} 1417 + 1418 standalone-electron-types@1.0.0: 1419 resolution: {integrity: sha512-0HOi/tlTz3mjWhsAz4uRbpQcHMZ+ifj1JzWW9nugykOHClBBG77ps8QinrzX1eow4Iw2pnC+RFaSYRgufF4BOg==} 1420 1421 + string.prototype.matchall@4.0.12: 1422 + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} 1423 engines: {node: '>= 0.4'} 1424 1425 string.prototype.repeat@1.0.0: 1426 resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} 1427 1428 + string.prototype.trim@1.2.10: 1429 + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} 1430 engines: {node: '>= 0.4'} 1431 1432 + string.prototype.trimend@1.0.9: 1433 + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} 1434 + engines: {node: '>= 0.4'} 1435 1436 string.prototype.trimstart@1.0.8: 1437 resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} ··· 1452 resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1453 engines: {node: '>= 0.4'} 1454 1455 + synckit@0.11.1: 1456 + resolution: {integrity: sha512-fWZqNBZNNFp/7mTUy1fSsydhKsAKJ+u90Nk7kOK5Gcq9vObaqLBLjWFDBkyVU9Vvc6Y71VbOevMuGhqv02bT+Q==} 1457 engines: {node: ^14.18.0 || >=16.0.0} 1458 1459 + taze@19.0.4: 1460 + resolution: {integrity: sha512-bviyNotzqcIWpVBCC4QYVb2yupzKyUDGQi2m/8GERdiPaudVMtgAqaE98+x0cDDaByYRMJCyhQWM04ikUL6+kQ==} 1461 + hasBin: true 1462 + 1463 + tinyexec@1.0.1: 1464 + resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} 1465 + 1466 + tinyglobby@0.2.12: 1467 + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} 1468 + engines: {node: '>=12.0.0'} 1469 1470 to-regex-range@5.0.1: 1471 resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1472 engines: {node: '>=8.0'} 1473 1474 + ts-api-utils@2.1.0: 1475 + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} 1476 + engines: {node: '>=18.12'} 1477 peerDependencies: 1478 + typescript: '>=4.8.4' 1479 1480 + tslib@2.8.1: 1481 + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 1482 1483 type-check@0.4.0: 1484 resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1485 engines: {node: '>= 0.8.0'} 1486 1487 + typed-array-buffer@1.0.3: 1488 + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} 1489 engines: {node: '>= 0.4'} 1490 1491 + typed-array-byte-length@1.0.3: 1492 + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} 1493 engines: {node: '>= 0.4'} 1494 1495 + typed-array-byte-offset@1.0.4: 1496 + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} 1497 engines: {node: '>= 0.4'} 1498 1499 + typed-array-length@1.0.7: 1500 + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} 1501 engines: {node: '>= 0.4'} 1502 1503 + typescript-eslint@8.29.0: 1504 + resolution: {integrity: sha512-ep9rVd9B4kQsZ7ZnWCVxUE/xDLUUUsRzE0poAeNu+4CkFErLfuvPt/qtm2EpnSyfvsR0S6QzDFSrPCFBwf64fg==} 1505 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 1506 peerDependencies: 1507 + eslint: ^8.57.0 || ^9.0.0 1508 + typescript: '>=4.8.4 <5.9.0' 1509 1510 + typescript@5.8.2: 1511 + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} 1512 engines: {node: '>=14.17'} 1513 hasBin: true 1514 1515 + ufo@1.5.4: 1516 + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} 1517 + 1518 + unbox-primitive@1.1.0: 1519 + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} 1520 + engines: {node: '>= 0.4'} 1521 + 1522 + unconfig@7.3.1: 1523 + resolution: {integrity: sha512-LH5WL+un92tGAzWS87k7LkAfwpMdm7V0IXG2FxEjZz/QxiIW5J5LkcrKQThj0aRz6+h/lFmKI9EUXmK/T0bcrw==} 1524 + 1525 + undici-types@6.20.0: 1526 + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} 1527 1528 + undici-types@6.21.0: 1529 + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} 1530 1531 uri-js@4.4.1: 1532 resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1533 1534 + utilium@1.10.1: 1535 + resolution: {integrity: sha512-GQINDTb/ocyz4acQj3GXAe0wipYxws6L+9ouqaq10KlInTk9DGvW9TJd0pYa/Xu3cppNnZuB4T/sBuSXpcN2ng==} 1536 1537 + which-boxed-primitive@1.1.1: 1538 + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} 1539 + engines: {node: '>= 0.4'} 1540 1541 + which-builtin-type@1.2.1: 1542 + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} 1543 engines: {node: '>= 0.4'} 1544 1545 which-collection@1.0.2: 1546 resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} 1547 engines: {node: '>= 0.4'} 1548 1549 + which-typed-array@1.1.19: 1550 + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} 1551 engines: {node: '>= 0.4'} 1552 1553 which@2.0.2: ··· 1555 engines: {node: '>= 8'} 1556 hasBin: true 1557 1558 + yaml@2.7.1: 1559 + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} 1560 + engines: {node: '>= 14'} 1561 + hasBin: true 1562 + 1563 yocto-queue@0.1.0: 1564 resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1565 engines: {node: '>=10'} 1566 1567 + zustand@5.0.3: 1568 + resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} 1569 + engines: {node: '>=12.20.0'} 1570 + peerDependencies: 1571 + '@types/react': '>=18.0.0' 1572 + immer: '>=9.0.6' 1573 + react: '>=18.0.0' 1574 + use-sync-external-store: '>=1.2.0' 1575 + peerDependenciesMeta: 1576 + '@types/react': 1577 + optional: true 1578 + immer: 1579 + optional: true 1580 + react: 1581 + optional: true 1582 + use-sync-external-store: 1583 + optional: true 1584 + 1585 snapshots: 1586 1587 '@aashutoshrathi/word-wrap@1.2.6': {} 1588 + 1589 + '@antfu/ni@24.3.0': 1590 + dependencies: 1591 + ansis: 3.17.0 1592 + fzf: 0.5.2 1593 + package-manager-detector: 1.1.0 1594 + tinyexec: 1.0.1 1595 1596 '@esbuild/android-arm64@0.19.3': 1597 optional: true ··· 1659 '@esbuild/win32-x64@0.19.3': 1660 optional: true 1661 1662 + '@eslint-community/eslint-utils@4.5.1(eslint@9.23.0(jiti@2.4.2))': 1663 dependencies: 1664 + eslint: 9.23.0(jiti@2.4.2) 1665 eslint-visitor-keys: 3.4.3 1666 1667 + '@eslint-community/regexpp@4.12.1': {} 1668 1669 + '@eslint/config-array@0.19.2': 1670 dependencies: 1671 + '@eslint/object-schema': 2.1.6 1672 + debug: 4.4.0 1673 minimatch: 3.1.2 1674 transitivePeerDependencies: 1675 - supports-color 1676 1677 + '@eslint/config-helpers@0.2.1': {} 1678 1679 + '@eslint/core@0.12.0': 1680 + dependencies: 1681 + '@types/json-schema': 7.0.15 1682 + 1683 + '@eslint/core@0.13.0': 1684 + dependencies: 1685 + '@types/json-schema': 7.0.15 1686 + 1687 + '@eslint/eslintrc@3.3.1': 1688 dependencies: 1689 ajv: 6.12.6 1690 + debug: 4.4.0 1691 + espree: 10.3.0 1692 globals: 14.0.0 1693 + ignore: 5.3.2 1694 import-fresh: 3.3.0 1695 js-yaml: 4.1.0 1696 minimatch: 3.1.2 ··· 1698 transitivePeerDependencies: 1699 - supports-color 1700 1701 + '@eslint/js@9.23.0': {} 1702 1703 + '@eslint/object-schema@2.1.6': {} 1704 1705 + '@eslint/plugin-kit@0.2.8': 1706 dependencies: 1707 + '@eslint/core': 0.13.0 1708 levn: 0.4.1 1709 1710 + '@humanfs/core@0.19.1': {} 1711 1712 + '@humanfs/node@0.16.6': 1713 dependencies: 1714 + '@humanfs/core': 0.19.1 1715 '@humanwhocodes/retry': 0.3.1 1716 1717 '@humanwhocodes/module-importer@1.0.1': {} 1718 1719 '@humanwhocodes/retry@0.3.1': {} 1720 1721 + '@humanwhocodes/retry@0.4.2': {} 1722 + 1723 + '@moonlight-mod/eslint-config@https://codeload.github.com/moonlight-mod/eslint-config/tar.gz/e262ac24e1a0955a9b3e0d66da247a0a8c0446c9(@types/eslint@9.6.1)(eslint@9.23.0(jiti@2.4.2))(prettier@3.1.0)(typescript@5.8.2)': 1724 dependencies: 1725 + '@eslint/js': 9.23.0 1726 + eslint: 9.23.0(jiti@2.4.2) 1727 + eslint-config-prettier: 9.1.0(eslint@9.23.0(jiti@2.4.2)) 1728 + eslint-plugin-prettier: 5.2.6(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.23.0(jiti@2.4.2)))(eslint@9.23.0(jiti@2.4.2))(prettier@3.1.0) 1729 + eslint-plugin-react: 7.37.5(eslint@9.23.0(jiti@2.4.2)) 1730 + typescript: 5.8.2 1731 + typescript-eslint: 8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) 1732 transitivePeerDependencies: 1733 - '@types/eslint' 1734 - prettier 1735 - supports-color 1736 1737 + '@moonlight-mod/lunast@1.0.1': 1738 dependencies: 1739 astring: 1.9.0 1740 estree-toolkit: 1.7.8 1741 meriyah: 6.0.1 1742 1743 + '@moonlight-mod/mappings@1.1.25(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5)': 1744 dependencies: 1745 + '@moonlight-mod/lunast': 1.0.1 1746 + '@moonlight-mod/moonmap': 1.0.5 1747 + '@types/chroma-js': 3.1.0 1748 '@types/flux': 3.1.14 1749 + '@types/highlightjs': 9.12.6 1750 + '@types/lodash': 4.17.14 1751 + '@types/platform': 1.3.6 1752 + '@types/react': 18.3.20 1753 csstype: 3.1.3 1754 + zustand: 5.0.3(@types/react@18.3.20) 1755 + transitivePeerDependencies: 1756 + - immer 1757 + - react 1758 + - use-sync-external-store 1759 1760 + '@moonlight-mod/moonmap@1.0.5': {} 1761 1762 '@nodelib/fs.scandir@2.1.5': 1763 dependencies: ··· 1771 '@nodelib/fs.scandir': 2.1.5 1772 fastq: 1.17.1 1773 1774 + '@pkgr/core@0.2.0': {} 1775 + 1776 + '@quansync/fs@0.1.2': 1777 + dependencies: 1778 + quansync: 0.2.10 1779 + 1780 + '@types/chroma-js@3.1.0': {} 1781 + 1782 + '@types/chrome@0.0.313': 1783 + dependencies: 1784 + '@types/filesystem': 0.0.36 1785 + '@types/har-format': 1.2.16 1786 + 1787 + '@types/eslint@9.6.1': 1788 + dependencies: 1789 + '@types/estree': 1.0.7 1790 + '@types/json-schema': 7.0.15 1791 + optional: true 1792 1793 '@types/estree-jsx@1.0.5': 1794 dependencies: 1795 '@types/estree': 1.0.6 1796 1797 '@types/estree@1.0.6': {} 1798 + 1799 + '@types/estree@1.0.7': 1800 + optional: true 1801 1802 '@types/fbemitter@2.0.35': {} 1803 1804 + '@types/filesystem@0.0.36': 1805 + dependencies: 1806 + '@types/filewriter': 0.0.33 1807 + 1808 + '@types/filewriter@0.0.33': {} 1809 + 1810 '@types/flux@3.1.14': 1811 dependencies: 1812 '@types/fbemitter': 2.0.35 1813 + '@types/react': 18.3.20 1814 + 1815 + '@types/har-format@1.2.16': {} 1816 + 1817 + '@types/highlightjs@9.12.6': {} 1818 1819 '@types/json-schema@7.0.15': {} 1820 1821 + '@types/lodash@4.17.14': {} 1822 + 1823 '@types/node@18.17.17': {} 1824 1825 + '@types/node@22.13.6': 1826 + dependencies: 1827 + undici-types: 6.20.0 1828 + 1829 + '@types/node@22.14.0': 1830 dependencies: 1831 + undici-types: 6.21.0 1832 + 1833 + '@types/platform@1.3.6': {} 1834 1835 '@types/prop-types@15.7.13': {} 1836 1837 + '@types/react@18.3.20': 1838 dependencies: 1839 '@types/prop-types': 15.7.13 1840 csstype: 3.1.3 1841 1842 + '@typescript-eslint/eslint-plugin@8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)': 1843 dependencies: 1844 + '@eslint-community/regexpp': 4.12.1 1845 + '@typescript-eslint/parser': 8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) 1846 + '@typescript-eslint/scope-manager': 8.29.0 1847 + '@typescript-eslint/type-utils': 8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) 1848 + '@typescript-eslint/utils': 8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) 1849 + '@typescript-eslint/visitor-keys': 8.29.0 1850 + eslint: 9.23.0(jiti@2.4.2) 1851 graphemer: 1.4.0 1852 ignore: 5.3.2 1853 natural-compare: 1.4.0 1854 + ts-api-utils: 2.1.0(typescript@5.8.2) 1855 + typescript: 5.8.2 1856 transitivePeerDependencies: 1857 - supports-color 1858 1859 + '@typescript-eslint/parser@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)': 1860 dependencies: 1861 + '@typescript-eslint/scope-manager': 8.29.0 1862 + '@typescript-eslint/types': 8.29.0 1863 + '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.8.2) 1864 + '@typescript-eslint/visitor-keys': 8.29.0 1865 + debug: 4.4.0 1866 + eslint: 9.23.0(jiti@2.4.2) 1867 + typescript: 5.8.2 1868 transitivePeerDependencies: 1869 - supports-color 1870 1871 + '@typescript-eslint/scope-manager@8.29.0': 1872 dependencies: 1873 + '@typescript-eslint/types': 8.29.0 1874 + '@typescript-eslint/visitor-keys': 8.29.0 1875 1876 + '@typescript-eslint/type-utils@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)': 1877 dependencies: 1878 + '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.8.2) 1879 + '@typescript-eslint/utils': 8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) 1880 + debug: 4.4.0 1881 + eslint: 9.23.0(jiti@2.4.2) 1882 + ts-api-utils: 2.1.0(typescript@5.8.2) 1883 + typescript: 5.8.2 1884 transitivePeerDependencies: 1885 - supports-color 1886 1887 + '@typescript-eslint/types@8.29.0': {} 1888 1889 + '@typescript-eslint/typescript-estree@8.29.0(typescript@5.8.2)': 1890 dependencies: 1891 + '@typescript-eslint/types': 8.29.0 1892 + '@typescript-eslint/visitor-keys': 8.29.0 1893 + debug: 4.4.0 1894 fast-glob: 3.3.2 1895 is-glob: 4.0.3 1896 minimatch: 9.0.5 1897 + semver: 7.7.1 1898 + ts-api-utils: 2.1.0(typescript@5.8.2) 1899 + typescript: 5.8.2 1900 transitivePeerDependencies: 1901 - supports-color 1902 1903 + '@typescript-eslint/utils@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)': 1904 dependencies: 1905 + '@eslint-community/eslint-utils': 4.5.1(eslint@9.23.0(jiti@2.4.2)) 1906 + '@typescript-eslint/scope-manager': 8.29.0 1907 + '@typescript-eslint/types': 8.29.0 1908 + '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.8.2) 1909 + eslint: 9.23.0(jiti@2.4.2) 1910 + typescript: 5.8.2 1911 transitivePeerDependencies: 1912 - supports-color 1913 1914 + '@typescript-eslint/visitor-keys@8.29.0': 1915 dependencies: 1916 + '@typescript-eslint/types': 8.29.0 1917 + eslint-visitor-keys: 4.2.0 1918 1919 + '@xterm/xterm@5.5.0': 1920 + optional: true 1921 + 1922 + '@zenfs/core@2.0.0': 1923 dependencies: 1924 + '@types/node': 22.13.6 1925 buffer: 6.0.3 1926 eventemitter3: 5.0.1 1927 readable-stream: 4.5.2 1928 + utilium: 1.10.1 1929 1930 + '@zenfs/dom@1.1.6(@zenfs/core@2.0.0)(utilium@1.10.1)': 1931 dependencies: 1932 + '@zenfs/core': 2.0.0 1933 + utilium: 1.10.1 1934 1935 abort-controller@3.0.0: 1936 dependencies: 1937 event-target-shim: 5.0.1 1938 1939 + acorn-jsx@5.3.2(acorn@8.14.1): 1940 dependencies: 1941 + acorn: 8.14.1 1942 1943 + acorn@8.14.1: {} 1944 1945 ajv@6.12.6: 1946 dependencies: ··· 1953 dependencies: 1954 color-convert: 2.0.1 1955 1956 + ansis@3.17.0: {} 1957 + 1958 argparse@2.0.1: {} 1959 1960 + array-buffer-byte-length@1.0.2: 1961 dependencies: 1962 + call-bound: 1.0.4 1963 + is-array-buffer: 3.0.5 1964 1965 array-includes@3.1.8: 1966 dependencies: 1967 + call-bind: 1.0.8 1968 define-properties: 1.2.1 1969 + es-abstract: 1.23.9 1970 + es-object-atoms: 1.1.1 1971 + get-intrinsic: 1.3.0 1972 + is-string: 1.1.1 1973 1974 array.prototype.findlast@1.2.5: 1975 dependencies: 1976 + call-bind: 1.0.8 1977 define-properties: 1.2.1 1978 + es-abstract: 1.23.9 1979 es-errors: 1.3.0 1980 + es-object-atoms: 1.1.1 1981 + es-shim-unscopables: 1.1.0 1982 1983 + array.prototype.flat@1.3.3: 1984 dependencies: 1985 + call-bind: 1.0.8 1986 define-properties: 1.2.1 1987 + es-abstract: 1.23.9 1988 + es-shim-unscopables: 1.1.0 1989 1990 + array.prototype.flatmap@1.3.3: 1991 dependencies: 1992 + call-bind: 1.0.8 1993 define-properties: 1.2.1 1994 + es-abstract: 1.23.9 1995 + es-shim-unscopables: 1.1.0 1996 1997 array.prototype.tosorted@1.1.4: 1998 dependencies: 1999 + call-bind: 1.0.8 2000 define-properties: 1.2.1 2001 + es-abstract: 1.23.9 2002 es-errors: 1.3.0 2003 + es-shim-unscopables: 1.1.0 2004 2005 + arraybuffer.prototype.slice@1.0.4: 2006 dependencies: 2007 + array-buffer-byte-length: 1.0.2 2008 + call-bind: 1.0.8 2009 define-properties: 1.2.1 2010 + es-abstract: 1.23.9 2011 es-errors: 1.3.0 2012 + get-intrinsic: 1.3.0 2013 + is-array-buffer: 3.0.5 2014 2015 astring@1.9.0: {} 2016 + 2017 + async-function@1.0.0: {} 2018 2019 available-typed-arrays@1.0.7: 2020 dependencies: 2021 + possible-typed-array-names: 1.1.0 2022 2023 balanced-match@1.0.2: {} 2024 ··· 2042 base64-js: 1.5.1 2043 ieee754: 1.2.1 2044 2045 + cac@6.7.14: {} 2046 + 2047 + call-bind-apply-helpers@1.0.2: 2048 dependencies: 2049 es-errors: 1.3.0 2050 function-bind: 1.1.2 2051 + 2052 + call-bind@1.0.8: 2053 + dependencies: 2054 + call-bind-apply-helpers: 1.0.2 2055 + es-define-property: 1.0.1 2056 + get-intrinsic: 1.3.0 2057 set-function-length: 1.2.2 2058 2059 + call-bound@1.0.4: 2060 + dependencies: 2061 + call-bind-apply-helpers: 1.0.2 2062 + get-intrinsic: 1.3.0 2063 + 2064 callsites@3.1.0: {} 2065 2066 chalk@4.1.2: ··· 2076 2077 concat-map@0.0.1: {} 2078 2079 + cross-spawn@7.0.6: 2080 dependencies: 2081 path-key: 3.1.1 2082 shebang-command: 2.0.0 2083 which: 2.0.2 2084 2085 csstype@3.1.3: {} 2086 2087 + data-view-buffer@1.0.2: 2088 dependencies: 2089 + call-bound: 1.0.4 2090 es-errors: 1.3.0 2091 + is-data-view: 1.0.2 2092 2093 + data-view-byte-length@1.0.2: 2094 dependencies: 2095 + call-bound: 1.0.4 2096 es-errors: 1.3.0 2097 + is-data-view: 1.0.2 2098 2099 + data-view-byte-offset@1.0.1: 2100 dependencies: 2101 + call-bound: 1.0.4 2102 es-errors: 1.3.0 2103 + is-data-view: 1.0.2 2104 2105 + debug@4.4.0: 2106 dependencies: 2107 + ms: 2.1.3 2108 2109 deep-is@0.1.4: {} 2110 2111 define-data-property@1.1.4: 2112 dependencies: 2113 + es-define-property: 1.0.1 2114 es-errors: 1.3.0 2115 + gopd: 1.2.0 2116 2117 define-properties@1.2.1: 2118 dependencies: ··· 2120 has-property-descriptors: 1.0.2 2121 object-keys: 1.1.1 2122 2123 + defu@6.1.4: {} 2124 + 2125 + destr@2.0.4: {} 2126 + 2127 doctrine@2.1.0: 2128 dependencies: 2129 esutils: 2.0.3 2130 2131 + dunder-proto@1.0.1: 2132 + dependencies: 2133 + call-bind-apply-helpers: 1.0.2 2134 + es-errors: 1.3.0 2135 + gopd: 1.2.0 2136 + 2137 + es-abstract@1.23.9: 2138 dependencies: 2139 + array-buffer-byte-length: 1.0.2 2140 + arraybuffer.prototype.slice: 1.0.4 2141 available-typed-arrays: 1.0.7 2142 + call-bind: 1.0.8 2143 + call-bound: 1.0.4 2144 + data-view-buffer: 1.0.2 2145 + data-view-byte-length: 1.0.2 2146 + data-view-byte-offset: 1.0.1 2147 + es-define-property: 1.0.1 2148 es-errors: 1.3.0 2149 + es-object-atoms: 1.1.1 2150 + es-set-tostringtag: 2.1.0 2151 + es-to-primitive: 1.3.0 2152 + function.prototype.name: 1.1.8 2153 + get-intrinsic: 1.3.0 2154 + get-proto: 1.0.1 2155 + get-symbol-description: 1.1.0 2156 globalthis: 1.0.4 2157 + gopd: 1.2.0 2158 has-property-descriptors: 1.0.2 2159 + has-proto: 1.2.0 2160 + has-symbols: 1.1.0 2161 hasown: 2.0.2 2162 + internal-slot: 1.1.0 2163 + is-array-buffer: 3.0.5 2164 is-callable: 1.2.7 2165 + is-data-view: 1.0.2 2166 + is-regex: 1.2.1 2167 + is-shared-array-buffer: 1.0.4 2168 + is-string: 1.1.1 2169 + is-typed-array: 1.1.15 2170 + is-weakref: 1.1.1 2171 + math-intrinsics: 1.1.0 2172 + object-inspect: 1.13.4 2173 object-keys: 1.1.1 2174 + object.assign: 4.1.7 2175 + own-keys: 1.0.1 2176 + regexp.prototype.flags: 1.5.4 2177 + safe-array-concat: 1.1.3 2178 + safe-push-apply: 1.0.0 2179 + safe-regex-test: 1.1.0 2180 + set-proto: 1.0.0 2181 + string.prototype.trim: 1.2.10 2182 + string.prototype.trimend: 1.0.9 2183 string.prototype.trimstart: 1.0.8 2184 + typed-array-buffer: 1.0.3 2185 + typed-array-byte-length: 1.0.3 2186 + typed-array-byte-offset: 1.0.4 2187 + typed-array-length: 1.0.7 2188 + unbox-primitive: 1.1.0 2189 + which-typed-array: 1.1.19 2190 2191 + es-define-property@1.0.1: {} 2192 2193 es-errors@1.3.0: {} 2194 2195 + es-iterator-helpers@1.2.1: 2196 dependencies: 2197 + call-bind: 1.0.8 2198 + call-bound: 1.0.4 2199 define-properties: 1.2.1 2200 + es-abstract: 1.23.9 2201 es-errors: 1.3.0 2202 + es-set-tostringtag: 2.1.0 2203 function-bind: 1.1.2 2204 + get-intrinsic: 1.3.0 2205 globalthis: 1.0.4 2206 + gopd: 1.2.0 2207 has-property-descriptors: 1.0.2 2208 + has-proto: 1.2.0 2209 + has-symbols: 1.1.0 2210 + internal-slot: 1.1.0 2211 + iterator.prototype: 1.1.5 2212 + safe-array-concat: 1.1.3 2213 2214 + es-object-atoms@1.1.1: 2215 dependencies: 2216 es-errors: 1.3.0 2217 2218 + es-set-tostringtag@2.1.0: 2219 dependencies: 2220 + es-errors: 1.3.0 2221 + get-intrinsic: 1.3.0 2222 has-tostringtag: 1.0.2 2223 hasown: 2.0.2 2224 2225 + es-shim-unscopables@1.1.0: 2226 dependencies: 2227 hasown: 2.0.2 2228 2229 + es-to-primitive@1.3.0: 2230 dependencies: 2231 is-callable: 1.2.7 2232 + is-date-object: 1.1.0 2233 + is-symbol: 1.1.1 2234 2235 esbuild-copy-static-files@0.1.0: {} 2236 ··· 2261 2262 escape-string-regexp@4.0.0: {} 2263 2264 + eslint-config-prettier@9.1.0(eslint@9.23.0(jiti@2.4.2)): 2265 dependencies: 2266 + eslint: 9.23.0(jiti@2.4.2) 2267 2268 + eslint-plugin-prettier@5.2.6(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.23.0(jiti@2.4.2)))(eslint@9.23.0(jiti@2.4.2))(prettier@3.1.0): 2269 dependencies: 2270 + eslint: 9.23.0(jiti@2.4.2) 2271 prettier: 3.1.0 2272 prettier-linter-helpers: 1.0.0 2273 + synckit: 0.11.1 2274 optionalDependencies: 2275 + '@types/eslint': 9.6.1 2276 + eslint-config-prettier: 9.1.0(eslint@9.23.0(jiti@2.4.2)) 2277 2278 + eslint-plugin-react@7.37.5(eslint@9.23.0(jiti@2.4.2)): 2279 dependencies: 2280 array-includes: 3.1.8 2281 array.prototype.findlast: 1.2.5 2282 + array.prototype.flatmap: 1.3.3 2283 array.prototype.tosorted: 1.1.4 2284 doctrine: 2.1.0 2285 + es-iterator-helpers: 1.2.1 2286 + eslint: 9.23.0(jiti@2.4.2) 2287 estraverse: 5.3.0 2288 hasown: 2.0.2 2289 jsx-ast-utils: 3.3.5 2290 minimatch: 3.1.2 2291 + object.entries: 1.1.9 2292 object.fromentries: 2.0.8 2293 + object.values: 1.2.1 2294 prop-types: 15.8.1 2295 resolve: 2.0.0-next.5 2296 semver: 6.3.1 2297 + string.prototype.matchall: 4.0.12 2298 string.prototype.repeat: 1.0.0 2299 2300 + eslint-scope@8.3.0: 2301 dependencies: 2302 esrecurse: 4.3.0 2303 estraverse: 5.3.0 2304 2305 eslint-visitor-keys@3.4.3: {} 2306 2307 + eslint-visitor-keys@4.2.0: {} 2308 2309 + eslint@9.23.0(jiti@2.4.2): 2310 dependencies: 2311 + '@eslint-community/eslint-utils': 4.5.1(eslint@9.23.0(jiti@2.4.2)) 2312 + '@eslint-community/regexpp': 4.12.1 2313 + '@eslint/config-array': 0.19.2 2314 + '@eslint/config-helpers': 0.2.1 2315 + '@eslint/core': 0.12.0 2316 + '@eslint/eslintrc': 3.3.1 2317 + '@eslint/js': 9.23.0 2318 + '@eslint/plugin-kit': 0.2.8 2319 + '@humanfs/node': 0.16.6 2320 '@humanwhocodes/module-importer': 1.0.1 2321 + '@humanwhocodes/retry': 0.4.2 2322 '@types/estree': 1.0.6 2323 '@types/json-schema': 7.0.15 2324 ajv: 6.12.6 2325 chalk: 4.1.2 2326 + cross-spawn: 7.0.6 2327 + debug: 4.4.0 2328 escape-string-regexp: 4.0.0 2329 + eslint-scope: 8.3.0 2330 + eslint-visitor-keys: 4.2.0 2331 + espree: 10.3.0 2332 + esquery: 1.6.0 2333 esutils: 2.0.3 2334 fast-deep-equal: 3.1.3 2335 file-entry-cache: 8.0.0 2336 find-up: 5.0.0 2337 glob-parent: 6.0.2 2338 + ignore: 5.3.2 2339 imurmurhash: 0.1.4 2340 is-glob: 4.0.3 2341 json-stable-stringify-without-jsonify: 1.0.1 ··· 2343 minimatch: 3.1.2 2344 natural-compare: 1.4.0 2345 optionator: 0.9.3 2346 + optionalDependencies: 2347 + jiti: 2.4.2 2348 transitivePeerDependencies: 2349 - supports-color 2350 2351 + espree@10.3.0: 2352 dependencies: 2353 + acorn: 8.14.1 2354 + acorn-jsx: 5.3.2(acorn@8.14.1) 2355 + eslint-visitor-keys: 4.2.0 2356 2357 + esquery@1.6.0: 2358 dependencies: 2359 estraverse: 5.3.0 2360 ··· 2397 dependencies: 2398 reusify: 1.0.4 2399 2400 + fdir@6.4.3(picomatch@4.0.2): 2401 + optionalDependencies: 2402 + picomatch: 4.0.2 2403 + 2404 file-entry-cache@8.0.0: 2405 dependencies: 2406 flat-cache: 4.0.1 ··· 2409 dependencies: 2410 to-regex-range: 5.0.1 2411 2412 + find-up-simple@1.0.1: {} 2413 + 2414 find-up@5.0.0: 2415 dependencies: 2416 locate-path: 6.0.0 ··· 2423 2424 flatted@3.2.9: {} 2425 2426 + for-each@0.3.5: 2427 dependencies: 2428 is-callable: 1.2.7 2429 2430 function-bind@1.1.2: {} 2431 2432 + function.prototype.name@1.1.8: 2433 dependencies: 2434 + call-bind: 1.0.8 2435 + call-bound: 1.0.4 2436 define-properties: 1.2.1 2437 functions-have-names: 1.2.3 2438 + hasown: 2.0.2 2439 + is-callable: 1.2.7 2440 2441 functions-have-names@1.2.3: {} 2442 2443 + fzf@0.5.2: {} 2444 + 2445 + get-intrinsic@1.3.0: 2446 dependencies: 2447 + call-bind-apply-helpers: 1.0.2 2448 + es-define-property: 1.0.1 2449 es-errors: 1.3.0 2450 + es-object-atoms: 1.1.1 2451 function-bind: 1.1.2 2452 + get-proto: 1.0.1 2453 + gopd: 1.2.0 2454 + has-symbols: 1.1.0 2455 hasown: 2.0.2 2456 + math-intrinsics: 1.1.0 2457 2458 + get-proto@1.0.1: 2459 dependencies: 2460 + dunder-proto: 1.0.1 2461 + es-object-atoms: 1.1.1 2462 + 2463 + get-symbol-description@1.1.0: 2464 + dependencies: 2465 + call-bound: 1.0.4 2466 es-errors: 1.3.0 2467 + get-intrinsic: 1.3.0 2468 2469 glob-parent@5.1.2: 2470 dependencies: ··· 2479 globalthis@1.0.4: 2480 dependencies: 2481 define-properties: 1.2.1 2482 + gopd: 1.2.0 2483 2484 + gopd@1.2.0: {} 2485 2486 graphemer@1.4.0: {} 2487 2488 + has-bigints@1.1.0: {} 2489 2490 has-flag@4.0.0: {} 2491 2492 has-property-descriptors@1.0.2: 2493 dependencies: 2494 + es-define-property: 1.0.1 2495 2496 + has-proto@1.2.0: 2497 + dependencies: 2498 + dunder-proto: 1.0.1 2499 2500 + has-symbols@1.1.0: {} 2501 2502 has-tostringtag@1.0.2: 2503 dependencies: 2504 + has-symbols: 1.1.0 2505 2506 hasown@2.0.2: 2507 dependencies: ··· 2510 husky@8.0.3: {} 2511 2512 ieee754@1.2.1: {} 2513 2514 ignore@5.3.2: {} 2515 ··· 2520 2521 imurmurhash@0.1.4: {} 2522 2523 + internal-slot@1.1.0: 2524 dependencies: 2525 es-errors: 1.3.0 2526 hasown: 2.0.2 2527 + side-channel: 1.1.0 2528 2529 + is-array-buffer@3.0.5: 2530 dependencies: 2531 + call-bind: 1.0.8 2532 + call-bound: 1.0.4 2533 + get-intrinsic: 1.3.0 2534 2535 + is-async-function@2.1.1: 2536 dependencies: 2537 + async-function: 1.0.0 2538 + call-bound: 1.0.4 2539 + get-proto: 1.0.1 2540 has-tostringtag: 1.0.2 2541 + safe-regex-test: 1.1.0 2542 2543 + is-bigint@1.1.0: 2544 dependencies: 2545 + has-bigints: 1.1.0 2546 2547 + is-boolean-object@1.2.2: 2548 dependencies: 2549 + call-bound: 1.0.4 2550 has-tostringtag: 1.0.2 2551 2552 is-callable@1.2.7: {} 2553 2554 + is-core-module@2.16.1: 2555 dependencies: 2556 hasown: 2.0.2 2557 2558 + is-data-view@1.0.2: 2559 dependencies: 2560 + call-bound: 1.0.4 2561 + get-intrinsic: 1.3.0 2562 + is-typed-array: 1.1.15 2563 2564 + is-date-object@1.1.0: 2565 dependencies: 2566 + call-bound: 1.0.4 2567 has-tostringtag: 1.0.2 2568 2569 is-extglob@2.1.1: {} 2570 2571 + is-finalizationregistry@1.1.1: 2572 dependencies: 2573 + call-bound: 1.0.4 2574 2575 + is-generator-function@1.1.0: 2576 dependencies: 2577 + call-bound: 1.0.4 2578 + get-proto: 1.0.1 2579 has-tostringtag: 1.0.2 2580 + safe-regex-test: 1.1.0 2581 2582 is-glob@4.0.3: 2583 dependencies: ··· 2585 2586 is-map@2.0.3: {} 2587 2588 + is-number-object@1.1.1: 2589 dependencies: 2590 + call-bound: 1.0.4 2591 has-tostringtag: 1.0.2 2592 2593 is-number@7.0.0: {} 2594 2595 + is-regex@1.2.1: 2596 dependencies: 2597 + call-bound: 1.0.4 2598 + gopd: 1.2.0 2599 has-tostringtag: 1.0.2 2600 + hasown: 2.0.2 2601 2602 is-set@2.0.3: {} 2603 2604 + is-shared-array-buffer@1.0.4: 2605 dependencies: 2606 + call-bound: 1.0.4 2607 2608 + is-string@1.1.1: 2609 dependencies: 2610 + call-bound: 1.0.4 2611 has-tostringtag: 1.0.2 2612 2613 + is-symbol@1.1.1: 2614 dependencies: 2615 + call-bound: 1.0.4 2616 + has-symbols: 1.1.0 2617 + safe-regex-test: 1.1.0 2618 2619 + is-typed-array@1.1.15: 2620 dependencies: 2621 + which-typed-array: 1.1.19 2622 2623 is-weakmap@2.0.2: {} 2624 2625 + is-weakref@1.1.1: 2626 dependencies: 2627 + call-bound: 1.0.4 2628 2629 + is-weakset@2.0.4: 2630 dependencies: 2631 + call-bound: 1.0.4 2632 + get-intrinsic: 1.3.0 2633 2634 isarray@2.0.5: {} 2635 2636 isexe@2.0.0: {} 2637 2638 + iterator.prototype@1.1.5: 2639 dependencies: 2640 + define-data-property: 1.1.4 2641 + es-object-atoms: 1.1.1 2642 + get-intrinsic: 1.3.0 2643 + get-proto: 1.0.1 2644 + has-symbols: 1.1.0 2645 set-function-name: 2.0.2 2646 2647 + jiti@2.4.2: {} 2648 + 2649 js-tokens@4.0.0: {} 2650 2651 js-yaml@4.1.0: ··· 2661 jsx-ast-utils@3.3.5: 2662 dependencies: 2663 array-includes: 3.1.8 2664 + array.prototype.flat: 1.3.3 2665 + object.assign: 4.1.7 2666 + object.values: 1.2.1 2667 2668 keyv@4.5.4: 2669 dependencies: ··· 2684 dependencies: 2685 js-tokens: 4.0.0 2686 2687 + math-intrinsics@1.1.0: {} 2688 + 2689 merge2@1.4.1: {} 2690 2691 meriyah@6.0.1: {} ··· 2696 dependencies: 2697 braces: 3.0.3 2698 picomatch: 2.3.1 2699 + 2700 + mimic-function@5.0.1: {} 2701 2702 minimatch@3.1.2: 2703 dependencies: ··· 2707 dependencies: 2708 brace-expansion: 2.0.1 2709 2710 + ms@2.1.3: {} 2711 2712 nanotar@0.1.1: {} 2713 2714 natural-compare@1.4.0: {} 2715 2716 + node-fetch-native@1.6.6: {} 2717 + 2718 object-assign@4.1.1: {} 2719 2720 + object-inspect@1.13.4: {} 2721 2722 object-keys@1.1.1: {} 2723 2724 + object.assign@4.1.7: 2725 dependencies: 2726 + call-bind: 1.0.8 2727 + call-bound: 1.0.4 2728 define-properties: 1.2.1 2729 + es-object-atoms: 1.1.1 2730 + has-symbols: 1.1.0 2731 object-keys: 1.1.1 2732 2733 + object.entries@1.1.9: 2734 dependencies: 2735 + call-bind: 1.0.8 2736 + call-bound: 1.0.4 2737 define-properties: 1.2.1 2738 + es-object-atoms: 1.1.1 2739 2740 object.fromentries@2.0.8: 2741 dependencies: 2742 + call-bind: 1.0.8 2743 define-properties: 1.2.1 2744 + es-abstract: 1.23.9 2745 + es-object-atoms: 1.1.1 2746 2747 + object.values@1.2.1: 2748 dependencies: 2749 + call-bind: 1.0.8 2750 + call-bound: 1.0.4 2751 define-properties: 1.2.1 2752 + es-object-atoms: 1.1.1 2753 + 2754 + ofetch@1.4.1: 2755 + dependencies: 2756 + destr: 2.0.4 2757 + node-fetch-native: 1.6.6 2758 + ufo: 1.5.4 2759 + 2760 + onetime@7.0.0: 2761 + dependencies: 2762 + mimic-function: 5.0.1 2763 2764 optionator@0.9.3: 2765 dependencies: ··· 2769 levn: 0.4.1 2770 prelude-ls: 1.2.1 2771 type-check: 0.4.0 2772 + 2773 + own-keys@1.0.1: 2774 + dependencies: 2775 + get-intrinsic: 1.3.0 2776 + object-keys: 1.1.1 2777 + safe-push-apply: 1.0.0 2778 2779 p-limit@3.1.0: 2780 dependencies: ··· 2784 dependencies: 2785 p-limit: 3.1.0 2786 2787 + package-manager-detector@1.1.0: {} 2788 + 2789 parent-module@1.0.1: 2790 dependencies: 2791 callsites: 3.1.0 ··· 2796 2797 path-parse@1.0.7: {} 2798 2799 + pathe@2.0.3: {} 2800 + 2801 picomatch@2.3.1: {} 2802 2803 + picomatch@4.0.2: {} 2804 + 2805 + pnpm-workspace-yaml@0.3.1: 2806 + dependencies: 2807 + yaml: 2.7.1 2808 + 2809 + possible-typed-array-names@1.1.0: {} 2810 2811 prelude-ls@1.2.1: {} 2812 ··· 2826 2827 punycode@2.3.1: {} 2828 2829 + quansync@0.2.10: {} 2830 + 2831 queue-microtask@1.2.3: {} 2832 2833 react-is@16.13.1: {} ··· 2840 process: 0.11.10 2841 string_decoder: 1.3.0 2842 2843 + reflect.getprototypeof@1.0.10: 2844 dependencies: 2845 + call-bind: 1.0.8 2846 define-properties: 1.2.1 2847 + es-abstract: 1.23.9 2848 es-errors: 1.3.0 2849 + es-object-atoms: 1.1.1 2850 + get-intrinsic: 1.3.0 2851 + get-proto: 1.0.1 2852 + which-builtin-type: 1.2.1 2853 2854 + regexp.prototype.flags@1.5.4: 2855 dependencies: 2856 + call-bind: 1.0.8 2857 define-properties: 1.2.1 2858 es-errors: 1.3.0 2859 + get-proto: 1.0.1 2860 + gopd: 1.2.0 2861 set-function-name: 2.0.2 2862 2863 resolve-from@4.0.0: {} 2864 2865 resolve@2.0.0-next.5: 2866 dependencies: 2867 + is-core-module: 2.16.1 2868 path-parse: 1.0.7 2869 supports-preserve-symlinks-flag: 1.0.0 2870 2871 + restore-cursor@5.1.0: 2872 + dependencies: 2873 + onetime: 7.0.0 2874 + signal-exit: 4.1.0 2875 + 2876 reusify@1.0.4: {} 2877 2878 run-parallel@1.2.0: 2879 dependencies: 2880 queue-microtask: 1.2.3 2881 2882 + safe-array-concat@1.1.3: 2883 dependencies: 2884 + call-bind: 1.0.8 2885 + call-bound: 1.0.4 2886 + get-intrinsic: 1.3.0 2887 + has-symbols: 1.1.0 2888 isarray: 2.0.5 2889 2890 safe-buffer@5.2.1: {} 2891 2892 + safe-push-apply@1.0.0: 2893 dependencies: 2894 es-errors: 1.3.0 2895 + isarray: 2.0.5 2896 + 2897 + safe-regex-test@1.1.0: 2898 + dependencies: 2899 + call-bound: 1.0.4 2900 + es-errors: 1.3.0 2901 + is-regex: 1.2.1 2902 2903 semver@6.3.1: {} 2904 2905 + semver@7.7.1: {} 2906 2907 set-function-length@1.2.2: 2908 dependencies: 2909 define-data-property: 1.1.4 2910 es-errors: 1.3.0 2911 function-bind: 1.1.2 2912 + get-intrinsic: 1.3.0 2913 + gopd: 1.2.0 2914 has-property-descriptors: 1.0.2 2915 2916 set-function-name@2.0.2: ··· 2920 functions-have-names: 1.2.3 2921 has-property-descriptors: 1.0.2 2922 2923 + set-proto@1.0.0: 2924 + dependencies: 2925 + dunder-proto: 1.0.1 2926 + es-errors: 1.3.0 2927 + es-object-atoms: 1.1.1 2928 + 2929 shebang-command@2.0.0: 2930 dependencies: 2931 shebang-regex: 3.0.0 2932 2933 shebang-regex@3.0.0: {} 2934 2935 + side-channel-list@1.0.0: 2936 + dependencies: 2937 + es-errors: 1.3.0 2938 + object-inspect: 1.13.4 2939 + 2940 + side-channel-map@1.0.1: 2941 + dependencies: 2942 + call-bound: 1.0.4 2943 + es-errors: 1.3.0 2944 + get-intrinsic: 1.3.0 2945 + object-inspect: 1.13.4 2946 + 2947 + side-channel-weakmap@1.0.2: 2948 + dependencies: 2949 + call-bound: 1.0.4 2950 + es-errors: 1.3.0 2951 + get-intrinsic: 1.3.0 2952 + object-inspect: 1.13.4 2953 + side-channel-map: 1.0.1 2954 + 2955 + side-channel@1.1.0: 2956 dependencies: 2957 es-errors: 1.3.0 2958 + object-inspect: 1.13.4 2959 + side-channel-list: 1.0.0 2960 + side-channel-map: 1.0.1 2961 + side-channel-weakmap: 1.0.2 2962 + 2963 + signal-exit@4.1.0: {} 2964 2965 standalone-electron-types@1.0.0: 2966 dependencies: 2967 '@types/node': 18.17.17 2968 2969 + string.prototype.matchall@4.0.12: 2970 dependencies: 2971 + call-bind: 1.0.8 2972 + call-bound: 1.0.4 2973 define-properties: 1.2.1 2974 + es-abstract: 1.23.9 2975 es-errors: 1.3.0 2976 + es-object-atoms: 1.1.1 2977 + get-intrinsic: 1.3.0 2978 + gopd: 1.2.0 2979 + has-symbols: 1.1.0 2980 + internal-slot: 1.1.0 2981 + regexp.prototype.flags: 1.5.4 2982 set-function-name: 2.0.2 2983 + side-channel: 1.1.0 2984 2985 string.prototype.repeat@1.0.0: 2986 dependencies: 2987 define-properties: 1.2.1 2988 + es-abstract: 1.23.9 2989 2990 + string.prototype.trim@1.2.10: 2991 dependencies: 2992 + call-bind: 1.0.8 2993 + call-bound: 1.0.4 2994 + define-data-property: 1.1.4 2995 define-properties: 1.2.1 2996 + es-abstract: 1.23.9 2997 + es-object-atoms: 1.1.1 2998 + has-property-descriptors: 1.0.2 2999 3000 + string.prototype.trimend@1.0.9: 3001 dependencies: 3002 + call-bind: 1.0.8 3003 + call-bound: 1.0.4 3004 define-properties: 1.2.1 3005 + es-object-atoms: 1.1.1 3006 3007 string.prototype.trimstart@1.0.8: 3008 dependencies: 3009 + call-bind: 1.0.8 3010 define-properties: 1.2.1 3011 + es-object-atoms: 1.1.1 3012 3013 string_decoder@1.3.0: 3014 dependencies: ··· 3022 3023 supports-preserve-symlinks-flag@1.0.0: {} 3024 3025 + synckit@0.11.1: 3026 + dependencies: 3027 + '@pkgr/core': 0.2.0 3028 + tslib: 2.8.1 3029 + 3030 + taze@19.0.4: 3031 dependencies: 3032 + '@antfu/ni': 24.3.0 3033 + cac: 6.7.14 3034 + find-up-simple: 1.0.1 3035 + ofetch: 1.4.1 3036 + package-manager-detector: 1.1.0 3037 + pathe: 2.0.3 3038 + pnpm-workspace-yaml: 0.3.1 3039 + restore-cursor: 5.1.0 3040 + tinyexec: 1.0.1 3041 + tinyglobby: 0.2.12 3042 + unconfig: 7.3.1 3043 + yaml: 2.7.1 3044 + 3045 + tinyexec@1.0.1: {} 3046 3047 + tinyglobby@0.2.12: 3048 + dependencies: 3049 + fdir: 6.4.3(picomatch@4.0.2) 3050 + picomatch: 4.0.2 3051 3052 to-regex-range@5.0.1: 3053 dependencies: 3054 is-number: 7.0.0 3055 3056 + ts-api-utils@2.1.0(typescript@5.8.2): 3057 dependencies: 3058 + typescript: 5.8.2 3059 3060 + tslib@2.8.1: {} 3061 3062 type-check@0.4.0: 3063 dependencies: 3064 prelude-ls: 1.2.1 3065 3066 + typed-array-buffer@1.0.3: 3067 dependencies: 3068 + call-bound: 1.0.4 3069 es-errors: 1.3.0 3070 + is-typed-array: 1.1.15 3071 3072 + typed-array-byte-length@1.0.3: 3073 dependencies: 3074 + call-bind: 1.0.8 3075 + for-each: 0.3.5 3076 + gopd: 1.2.0 3077 + has-proto: 1.2.0 3078 + is-typed-array: 1.1.15 3079 3080 + typed-array-byte-offset@1.0.4: 3081 dependencies: 3082 available-typed-arrays: 1.0.7 3083 + call-bind: 1.0.8 3084 + for-each: 0.3.5 3085 + gopd: 1.2.0 3086 + has-proto: 1.2.0 3087 + is-typed-array: 1.1.15 3088 + reflect.getprototypeof: 1.0.10 3089 3090 + typed-array-length@1.0.7: 3091 dependencies: 3092 + call-bind: 1.0.8 3093 + for-each: 0.3.5 3094 + gopd: 1.2.0 3095 + is-typed-array: 1.1.15 3096 + possible-typed-array-names: 1.1.0 3097 + reflect.getprototypeof: 1.0.10 3098 3099 + typescript-eslint@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2): 3100 dependencies: 3101 + '@typescript-eslint/eslint-plugin': 8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) 3102 + '@typescript-eslint/parser': 8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) 3103 + '@typescript-eslint/utils': 8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) 3104 + eslint: 9.23.0(jiti@2.4.2) 3105 + typescript: 5.8.2 3106 transitivePeerDependencies: 3107 - supports-color 3108 3109 + typescript@5.8.2: {} 3110 + 3111 + ufo@1.5.4: {} 3112 + 3113 + unbox-primitive@1.1.0: 3114 + dependencies: 3115 + call-bound: 1.0.4 3116 + has-bigints: 1.1.0 3117 + has-symbols: 1.1.0 3118 + which-boxed-primitive: 1.1.1 3119 3120 + unconfig@7.3.1: 3121 dependencies: 3122 + '@quansync/fs': 0.1.2 3123 + defu: 6.1.4 3124 + jiti: 2.4.2 3125 + quansync: 0.2.10 3126 + 3127 + undici-types@6.20.0: {} 3128 3129 + undici-types@6.21.0: {} 3130 3131 uri-js@4.4.1: 3132 dependencies: 3133 punycode: 2.3.1 3134 3135 + utilium@1.10.1: 3136 dependencies: 3137 eventemitter3: 5.0.1 3138 + optionalDependencies: 3139 + '@xterm/xterm': 5.5.0 3140 3141 + which-boxed-primitive@1.1.1: 3142 dependencies: 3143 + is-bigint: 1.1.0 3144 + is-boolean-object: 1.2.2 3145 + is-number-object: 1.1.1 3146 + is-string: 1.1.1 3147 + is-symbol: 1.1.1 3148 3149 + which-builtin-type@1.2.1: 3150 dependencies: 3151 + call-bound: 1.0.4 3152 + function.prototype.name: 1.1.8 3153 has-tostringtag: 1.0.2 3154 + is-async-function: 2.1.1 3155 + is-date-object: 1.1.0 3156 + is-finalizationregistry: 1.1.1 3157 + is-generator-function: 1.1.0 3158 + is-regex: 1.2.1 3159 + is-weakref: 1.1.1 3160 isarray: 2.0.5 3161 + which-boxed-primitive: 1.1.1 3162 which-collection: 1.0.2 3163 + which-typed-array: 1.1.19 3164 3165 which-collection@1.0.2: 3166 dependencies: 3167 is-map: 2.0.3 3168 is-set: 2.0.3 3169 is-weakmap: 2.0.2 3170 + is-weakset: 2.0.4 3171 3172 + which-typed-array@1.1.19: 3173 dependencies: 3174 available-typed-arrays: 1.0.7 3175 + call-bind: 1.0.8 3176 + call-bound: 1.0.4 3177 + for-each: 0.3.5 3178 + get-proto: 1.0.1 3179 + gopd: 1.2.0 3180 has-tostringtag: 1.0.2 3181 3182 which@2.0.2: 3183 dependencies: 3184 isexe: 2.0.0 3185 3186 + yaml@2.7.1: {} 3187 + 3188 yocto-queue@0.1.0: {} 3189 + 3190 + zustand@5.0.3(@types/react@18.3.20): 3191 + optionalDependencies: 3192 + '@types/react': 18.3.20
+31 -1
pnpm-workspace.yaml
··· 1 packages: 2 - - "packages/*"
··· 1 packages: 2 + - packages/* 3 + 4 + catalogs: 5 + dev: 6 + esbuild: ^0.19.3 7 + esbuild-copy-static-files: ^0.1.0 8 + "@types/node": ^22.14.0 9 + "@moonlight-mod/eslint-config": "github:moonlight-mod/eslint-config" 10 + eslint: ^9.12.0 11 + "@types/chrome": ^0.0.313 12 + husky: ^8.0.3 13 + prettier: ^3.1.0 14 + typescript: ^5.3.3 15 + taze: ^19.0.4 16 + prod: 17 + "@moonlight-mod/lunast": ^1.0.1 18 + "@moonlight-mod/mappings": ^1.1.25 19 + "@moonlight-mod/moonmap": ^1.0.5 20 + microdiff: ^1.5.0 21 + nanotar: ^0.1.1 22 + "@zenfs/core": ^2.0.0 23 + "@zenfs/dom": ^1.1.3 24 + 25 + onlyBuiltDependencies: 26 + - esbuild 27 + 28 + engineStrict: true 29 + strictSsl: true 30 + strictDepBuilds: true 31 + packageManagerStrict: true 32 + registry: https://registry.npmjs.org/
-78
scripts/link.js
··· 1 - // Janky script to get around pnpm link issues 2 - // Probably don't use this. Probably 3 - /* eslint-disable no-console */ 4 - const fs = require("fs"); 5 - const path = require("path"); 6 - const child_process = require("child_process"); 7 - 8 - const cwd = process.cwd(); 9 - const onDisk = { 10 - "@moonlight-mod/lunast": "../lunast", 11 - "@moonlight-mod/moonmap": "../moonmap", 12 - "@moonlight-mod/mappings": "../mappings" 13 - }; 14 - 15 - function exec(cmd, dir) { 16 - child_process.execSync(cmd, { cwd: dir, stdio: "inherit" }); 17 - } 18 - 19 - function getDeps(packageJSON) { 20 - const ret = {}; 21 - Object.assign(ret, packageJSON.dependencies || {}); 22 - Object.assign(ret, packageJSON.devDependencies || {}); 23 - Object.assign(ret, packageJSON.peerDependencies || {}); 24 - return ret; 25 - } 26 - 27 - function link(dir) { 28 - const packageJSONPath = path.join(dir, "package.json"); 29 - if (!fs.existsSync(packageJSONPath)) return; 30 - const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, "utf8")); 31 - const deps = getDeps(packageJSON); 32 - 33 - for (const [dep, relativePath] of Object.entries(onDisk)) { 34 - const fullPath = path.join(cwd, relativePath); 35 - if (deps[dep]) { 36 - exec(`pnpm link ${fullPath}`, dir); 37 - } 38 - } 39 - } 40 - 41 - function undo(dir) { 42 - exec("pnpm unlink", dir); 43 - try { 44 - if (fs.existsSync(path.join(dir, "pnpm-lock.yaml"))) { 45 - exec("git restore pnpm-lock.yaml", dir); 46 - } 47 - } catch { 48 - // ignored 49 - } 50 - } 51 - 52 - const shouldUndo = process.argv.includes("--undo"); 53 - const packages = fs.readdirSync("./packages"); 54 - 55 - for (const path of Object.values(onDisk)) { 56 - console.log(path); 57 - if (shouldUndo) { 58 - undo(path); 59 - } else { 60 - link(path); 61 - } 62 - } 63 - 64 - if (shouldUndo) { 65 - console.log(cwd); 66 - undo(cwd); 67 - for (const pkg of packages) { 68 - const dir = path.join(cwd, "packages", pkg); 69 - console.log(dir); 70 - undo(dir); 71 - } 72 - } else { 73 - for (const pkg of packages) { 74 - const dir = path.join(cwd, "packages", pkg); 75 - console.log(dir); 76 - link(dir); 77 - } 78 - }
···
+78
scripts/link.mjs
···
··· 1 + // Janky script to get around pnpm link issues 2 + // Probably don't use this. Probably 3 + /* eslint-disable no-console */ 4 + const fs = require("fs"); 5 + const path = require("path"); 6 + const child_process = require("child_process"); 7 + 8 + const cwd = process.cwd(); 9 + const onDisk = { 10 + //"@moonlight-mod/lunast": "../lunast", 11 + //"@moonlight-mod/moonmap": "../moonmap", 12 + "@moonlight-mod/mappings": "../mappings" 13 + }; 14 + 15 + function exec(cmd, dir) { 16 + child_process.execSync(cmd, { cwd: dir, stdio: "inherit" }); 17 + } 18 + 19 + function getDeps(packageJSON) { 20 + const ret = {}; 21 + Object.assign(ret, packageJSON.dependencies || {}); 22 + Object.assign(ret, packageJSON.devDependencies || {}); 23 + Object.assign(ret, packageJSON.peerDependencies || {}); 24 + return ret; 25 + } 26 + 27 + function link(dir) { 28 + const packageJSONPath = path.join(dir, "package.json"); 29 + if (!fs.existsSync(packageJSONPath)) return; 30 + const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, "utf8")); 31 + const deps = getDeps(packageJSON); 32 + 33 + for (const [dep, relativePath] of Object.entries(onDisk)) { 34 + const fullPath = path.join(cwd, relativePath); 35 + if (deps[dep]) { 36 + exec(`pnpm link ${fullPath}`, dir); 37 + } 38 + } 39 + } 40 + 41 + function undo(dir) { 42 + exec("pnpm unlink", dir); 43 + try { 44 + if (fs.existsSync(path.join(dir, "pnpm-lock.yaml"))) { 45 + exec("git restore pnpm-lock.yaml", dir); 46 + } 47 + } catch { 48 + // ignored 49 + } 50 + } 51 + 52 + const shouldUndo = process.argv.includes("--undo"); 53 + const packages = fs.readdirSync("./packages"); 54 + 55 + for (const path of Object.values(onDisk)) { 56 + console.log(path); 57 + if (shouldUndo) { 58 + undo(path); 59 + } else { 60 + link(path); 61 + } 62 + } 63 + 64 + if (shouldUndo) { 65 + console.log(cwd); 66 + undo(cwd); 67 + for (const pkg of packages) { 68 + const dir = path.join(cwd, "packages", pkg); 69 + console.log(dir); 70 + undo(dir); 71 + } 72 + } else { 73 + for (const pkg of packages) { 74 + const dir = path.join(cwd, "packages", pkg); 75 + console.log(dir); 76 + link(dir); 77 + } 78 + }
-29
scripts/update.js
··· 1 - // Update dependencies in all packages 2 - /* eslint-disable no-console */ 3 - const fs = require("fs"); 4 - const path = require("path"); 5 - const child_process = require("child_process"); 6 - 7 - const packageToUpdate = process.argv[2]; 8 - 9 - function getDeps(packageJSON) { 10 - const ret = {}; 11 - Object.assign(ret, packageJSON.dependencies || {}); 12 - Object.assign(ret, packageJSON.devDependencies || {}); 13 - Object.assign(ret, packageJSON.peerDependencies || {}); 14 - return ret; 15 - } 16 - 17 - function exec(cmd, dir) { 18 - child_process.execSync(cmd, { cwd: dir, stdio: "inherit" }); 19 - } 20 - 21 - for (const package of fs.readdirSync("./packages")) { 22 - const packageJSON = JSON.parse(fs.readFileSync(path.join("./packages", package, "package.json"), "utf8")); 23 - 24 - const deps = getDeps(packageJSON); 25 - if (Object.keys(deps).includes(packageToUpdate)) { 26 - console.log(`Updating ${packageToUpdate} in ${package}`); 27 - exec(`pnpm update ${packageToUpdate}`, path.join("./packages", package)); 28 - } 29 - }
···
+35
tsconfig.base.json
···
··· 1 + { 2 + "$schema": "https://json.schemastore.org/tsconfig.json", 3 + "display": "Base", 4 + "_version": "1.0.0", 5 + "compilerOptions": { 6 + "incremental": true, 7 + "target": "ES2022", 8 + "jsx": "react", 9 + "lib": ["ESNext", "ESNext.Disposable", "DOM", "DOM.Iterable"], 10 + "module": "ES2020", 11 + "moduleResolution": "Bundler", 12 + "resolveJsonModule": true, 13 + "allowArbitraryExtensions": false, 14 + "allowImportingTsExtensions": true, 15 + "allowJs": true, 16 + "strict": true, 17 + "strictNullChecks": true, 18 + 19 + // disable unreachable code detection because it breaks with esbuild labels 20 + "allowUnreachableCode": true, 21 + "noFallthroughCasesInSwitch": true, 22 + "noImplicitReturns": true, 23 + "declaration": true, 24 + "declarationMap": true, 25 + "outDir": "dist", 26 + "sourceMap": true, 27 + "stripInternal": true, 28 + "esModuleInterop": true, 29 + "forceConsistentCasingInFileNames": true, 30 + "noErrorTruncation": true, 31 + "verbatimModuleSyntax": false, 32 + // meriyah has a broken import lol 33 + "skipLibCheck": true 34 + } 35 + }
+7 -16
tsconfig.json
··· 1 { 2 "compilerOptions": { 3 - "target": "es2022", 4 - "module": "es2020", 5 - "esModuleInterop": true, 6 - "forceConsistentCasingInFileNames": true, 7 - "strict": true, 8 - "moduleResolution": "bundler", 9 "baseUrl": "./packages/", 10 - "jsx": "react", 11 - "noEmit": true, 12 - 13 - // meriyah has a broken import lol 14 - "skipLibCheck": true, 15 - 16 - // disable unreachable code detection because it breaks with esbuild labels 17 - "allowUnreachableCode": true 18 }, 19 - "include": ["./packages/**/*", "./env.d.ts"], 20 - "exclude": ["node_modules"] 21 }
··· 1 { 2 + "extends": ["./tsconfig.base.json"], 3 "compilerOptions": { 4 "baseUrl": "./packages/", 5 + "noEmit": true 6 }, 7 + "exclude": [ 8 + "**/node_modules/**", 9 + "**/dist/**", 10 + "**/build/**" 11 + ] 12 }