this repo has no description

Compare changes

Choose any two refs to compare.

Changed files
+5330 -1828
.github
nix
packages
browser
core
core-extensions
injector
node-preload
types
web-preload
scripts
+4 -8
.github/workflows/browser.yml
··· 10 10 name: Browser extension builds 11 11 runs-on: ubuntu-latest 12 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 13 + - uses: actions/checkout@v4 14 + - uses: pnpm/action-setup@v4 15 + - uses: actions/setup-node@v4 20 16 with: 21 - node-version: 18 17 + node-version: 22 22 18 cache: pnpm 23 19 24 20 - name: Install dependencies
+4 -8
.github/workflows/lint.yml
··· 9 9 name: Lint commits 10 10 runs-on: ubuntu-latest 11 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 12 + - uses: actions/checkout@v4 13 + - uses: pnpm/action-setup@v4 14 + - uses: actions/setup-node@v4 19 15 with: 20 - node-version: 18 16 + node-version: 22 21 17 cache: pnpm 22 18 23 19 - name: Install dependencies
+4 -8
.github/workflows/nightly.yml
··· 15 15 name: Nightly builds on GitHub Pages 16 16 runs-on: ubuntu-latest 17 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 18 + - uses: actions/checkout@v4 19 + - uses: pnpm/action-setup@v4 20 + - uses: actions/setup-node@v4 25 21 with: 26 - node-version: 18 22 + node-version: 22 27 23 cache: pnpm 28 24 29 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 13 name: Release builds to GitHub Releases 14 14 runs-on: ubuntu-latest 15 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 16 + - uses: actions/checkout@v4 17 + - uses: pnpm/action-setup@v4 18 + - uses: actions/setup-node@v4 23 19 with: 24 - node-version: 18 20 + node-version: 22 25 21 cache: pnpm 26 22 27 23 - name: Install dependencies
+5 -11
.github/workflows/types.yml
··· 11 11 name: Publish types on npm 12 12 runs-on: ubuntu-latest 13 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 14 + - uses: actions/checkout@v4 15 + - uses: pnpm/action-setup@v4 16 + - uses: actions/setup-node@v4 21 17 with: 22 - node-version: 18 18 + node-version: 22 23 19 cache: pnpm 24 20 registry-url: https://registry.npmjs.org 25 21 ··· 31 27 run: pnpm run build 32 28 33 29 - name: Publish types 34 - run: | 35 - cd packages/types 36 - pnpm publish --access public --no-git-checks 30 + run: pnpm publish --filter=./packages/types --access public --no-git-checks 37 31 env: 38 32 NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+1 -1
.gitignore
··· 3 3 dist.tar.gz 4 4 .DS_Store 5 5 eslint_report.json 6 - 6 + .eslintcache 7 7 # Nix 8 8 /result 9 9 *.drv
+4 -4
.prettierrc
··· 1 1 { 2 - "printWidth": 120, 3 - "trailingComma": "none", 4 - "tabWidth": 2, 5 - "singleQuote": false 2 + "printWidth": 120, 3 + "trailingComma": "none", 4 + "tabWidth": 2, 5 + "singleQuote": false 6 6 }
+2 -61
CHANGELOG.md
··· 1 - ## Moonbase 2 - 3 - - Overhauled restart notifications 4 - - Moonbase now waits for the user to save their changes before prompting to restart the client 5 - - Restarting the client in Moonbase now *fully* restarts the client when needed 6 - - Allowed extensions to specify "restart advice" for settings 7 - - Improved update systems 8 - - Fixed the update banner having an invisible close button 9 - - Made updates clearer in Moonbase by adding a divider + filter 10 - - Extension settings now update immediately after updating, without having to restart 11 - - Added extension changelogs (`meta.changelog` in the manifest) 12 - - Added a refresh button to Moonbase 13 - - Added the ability to update moonlight from the system tray 14 - - Moonbase now warns the user when enabling a dangerous extension 15 - - Moonbase now checks the extension author when using the search filter 16 - - Added a tooltip for conflicting extensions in Moonbase 17 - - Added basic crash cause detection 18 - 19 1 ## Core 20 2 21 - - Reworked core loading to properly be asynchronous, fixing race conditions 22 - - **A full client restart is required when updating to this version!** 23 - - If you have any issues starting your client, or moonlight does not load, let us know! 24 - - Special thanks to @gBasil for helping us find this issue. 25 - - Added better support for `\i` in patching and Spacepack 26 - - Added better error handling in entrypoint Webpack modules to prevent crashes 27 - - Added hard fail/"grouping" to patches 28 - - Added being able to patch mapped modules by referencing their name in the patch find 29 - - Fixed a bug with extensions patching the same Webpack module 30 - - Special thanks to @karashiiro for helping us find this issue. 31 - - Added API parity to all moonlight global variables 32 - - Updated all core extension manifests 33 - - Added an optional config to the injector for special installation setups 34 - 35 - ## Documentation 36 - 37 - - Updated the GitHub README and project website 38 - - Added "Why moonlight?" section to the project website 39 - - Updated Starlight 40 - - Added better documentation for all core extensions 41 - - Documented the new moonlight features 42 - - Added documentation for writing mappings 43 - - Added note about auto-detected Linux installs and running as root 44 - - Added clearer download buttons for the moonlight installer 45 - - Documented installing moonlight through Nix 46 - - Added contribution guidelines 47 - - Added reminder to restart fully when adding React DevTools 48 - - Mention all files when editing the sample extension 49 - - Documented extension manifests 50 - - Documented adding types for Webpack module import statements 51 - - Clarified how moonlight environments and globals behave 52 - - Fixed an invalid suggestion for matching yourself with Spacepack 53 - - Performed a general cleanup pass on grammar 54 - 55 - ## Misc 56 - 57 - - Fixed Nix support by updating pnpm2nix (thank you @sersorrel!) 58 - - Cleaned up the installer (thank you @pauliesnug!) 59 - - Updated deprecated GitHub Actions to the latest version 60 - - Updated & cleaned up sample extension 61 - - Fixed auth requirement for RoboJules 62 - - Merged 9 new extensions (thank you @Cynosphere, @redstonekasi!) 63 - - Cleaned up GitHub organization permissions by moving to teams 3 + - Updated mappings 4 + - Fixed using remapped paths as patch finds not working
+1 -1
README.md
··· 23 23 24 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 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. 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 27 28 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 18 "type": "github" 19 19 } 20 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 21 "nixpkgs": { 40 22 "locked": { 41 - "lastModified": 1728067476, 42 - "narHash": "sha256-/uJcVXuBt+VFCPQIX+4YnYrHaubJSx4HoNsJVNRgANM=", 23 + "lastModified": 1744232761, 24 + "narHash": "sha256-gbl9hE39nQRpZaLjhWKmEu5ejtQsgI5TWYrIVVJn30U=", 43 25 "owner": "NixOS", 44 26 "repo": "nixpkgs", 45 - "rev": "6e6b3dd395c3b1eb9be9f2d096383a8d05add030", 27 + "rev": "f675531bc7e6657c10a18b565cfebd8aa9e24c14", 46 28 "type": "github" 47 29 }, 48 30 "original": { 49 31 "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 32 "ref": "nixos-unstable", 67 33 "repo": "nixpkgs", 68 34 "type": "github" 69 35 } 70 36 }, 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 37 "root": { 91 38 "inputs": { 92 39 "flake-utils": "flake-utils", 93 - "nixpkgs": "nixpkgs", 94 - "pnpm2nix": "pnpm2nix" 40 + "nixpkgs": "nixpkgs" 95 41 } 96 42 }, 97 43 "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 44 "locked": { 114 45 "lastModified": 1681028828, 115 46 "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+3 -4
flake.nix
··· 2 2 description = "Yet another Discord mod"; 3 3 4 4 inputs = { 5 - nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; 5 + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 6 flake-utils.url = "github:numtide/flake-utils"; 7 - pnpm2nix.url = "github:NotNite/pnpm2nix-nzbr"; 8 7 }; 9 8 10 - outputs = { self, nixpkgs, flake-utils, pnpm2nix }: 11 - let overlay = import ./nix/overlay.nix { inherit pnpm2nix; }; 9 + outputs = { self, nixpkgs, flake-utils }: 10 + let overlay = import ./nix/overlay.nix { }; 12 11 in flake-utils.lib.eachDefaultSystem (system: 13 12 let 14 13 pkgs = import nixpkgs {
+46 -17
nix/default.nix
··· 1 - { pkgs, mkPnpmPackage }: 1 + { 2 + lib, 3 + stdenv, 4 + nodejs_22, 5 + pnpm_10, 6 + }: 2 7 3 - mkPnpmPackage rec { 4 - workspace = ./..; 8 + stdenv.mkDerivation (finalAttrs: { 9 + pname = "moonlight"; 10 + version = (builtins.fromJSON (builtins.readFile ./../package.json)).version; 11 + 5 12 src = ./..; 6 13 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" 14 + outputs = [ "out" "firefox" ]; 15 + 16 + nativeBuildInputs = [ 17 + nodejs_22 18 + pnpm_10.configHook 15 19 ]; 16 - distDirs = [ "dist" ]; 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 17 42 18 - copyNodeModules = true; 19 - buildPhase = "pnpm run build"; 20 - installPhase = "cp -r dist $out"; 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 + ''; 21 50 22 - meta = with pkgs.lib; { 51 + meta = with lib; { 23 52 description = "Yet another Discord mod"; 24 53 homepage = "https://moonlight-mod.github.io/"; 25 54 license = licenses.lgpl3; 26 55 maintainers = with maintainers; [ notnite ]; 27 56 }; 28 - } 57 + })
+3 -6
nix/overlay.nix
··· 1 - { pnpm2nix }: 1 + { ... }: 2 2 3 3 let 4 4 nameTable = { ··· 29 29 ''; 30 30 31 31 packageJson = '' 32 - {"name":"discord","main":"./injector.js","private":true} 32 + {"name":"${name}","main":"./injector.js","private":true} 33 33 ''; 34 34 35 35 in old.installPhase + "\n" + '' ··· 49 49 ''; 50 50 }); 51 51 in final: prev: rec { 52 - moonlight-mod = final.callPackage ./default.nix { 53 - pkgs = final; 54 - mkPnpmPackage = pnpm2nix.packages.${final.system}.mkPnpmPackage; 55 - }; 52 + moonlight-mod = final.callPackage ./default.nix { }; 56 53 discord = mkOverride prev moonlight-mod "discord"; 57 54 discord-ptb = mkOverride prev moonlight-mod "discord-ptb"; 58 55 discord-canary = mkOverride prev moonlight-mod "discord-canary";
+23 -12
package.json
··· 1 1 { 2 2 "name": "moonlight", 3 - "version": "1.3.0", 3 + "version": "1.3.14", 4 + "packageManager": "pnpm@10.7.1", 4 5 "description": "Yet another Discord mod", 5 - "homepage": "https://moonlight-mod.github.io/", 6 6 "license": "LGPL-3.0-or-later", 7 + "homepage": "https://moonlight-mod.github.io/", 7 8 "repository": { 8 9 "type": "git", 9 10 "url": "git+https://github.com/moonlight-mod/moonlight.git" ··· 11 12 "bugs": { 12 13 "url": "https://github.com/moonlight-mod/moonlight/issues" 13 14 }, 15 + "engineStrict": true, 16 + "engines": { 17 + "node": ">=22", 18 + "pnpm": ">=10", 19 + "npm": "pnpm", 20 + "yarn": "pnpm" 21 + }, 14 22 "scripts": { 15 23 "build": "node build.mjs", 16 24 "dev": "node build.mjs --watch", ··· 18 26 "browser": "node build.mjs --browser", 19 27 "browser-mv2": "node build.mjs --browser --mv2", 20 28 "lint": "eslint packages", 21 - "lint:fix": "eslint packages --fix", 22 - "lint:report": "eslint --output-file eslint_report.json --format json packages", 29 + "lint:fix": "pnpm lint --fix", 30 + "lint:report": "pnpm lint --output-file eslint_report.json --format json", 23 31 "typecheck": "tsc --noEmit", 24 32 "check": "pnpm run lint && pnpm run typecheck", 25 - "prepare": "husky install" 33 + "prepare": "husky install", 34 + "updates": "pnpm taze -r" 26 35 }, 27 36 "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" 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" 35 46 } 36 47 }
+2 -1
packages/browser/blockLoading.json
··· 6 6 "type": "block" 7 7 }, 8 8 "condition": { 9 - "urlFilter": "*://discord.com/assets/*.js", 9 + "requestDomains": ["discord.com", "discordapp.com"], 10 + "urlFilter": "*/assets/*.js", 10 11 "resourceTypes": ["script"] 11 12 } 12 13 }
+10 -4
packages/browser/manifest.json
··· 1 1 { 2 + "$schema": "https://json.schemastore.org/chrome-manifest", 2 3 "manifest_version": 3, 3 4 "name": "moonlight", 4 5 "description": "Yet another Discord mod", 5 - "version": "1.3.0", 6 + "version": "1.3.14", 6 7 "permissions": ["declarativeNetRequestWithHostAccess", "webRequest", "scripting", "webNavigation"], 7 - "host_permissions": ["https://moonlight-mod.github.io/*", "https://api.github.com/*", "https://*.discord.com/*"], 8 + "host_permissions": [ 9 + "https://moonlight-mod.github.io/*", 10 + "https://api.github.com/*", 11 + "https://*.discord.com/*", 12 + "https://*.discordapp.com/*" 13 + ], 8 14 "content_scripts": [ 9 15 { 10 16 "js": ["index.js"], 11 - "matches": ["https://*.discord.com/*"], 17 + "matches": ["https://*.discord.com/*", "https://*.discordapp.com/*"], 12 18 "run_at": "document_start", 13 19 "world": "MAIN" 14 20 } ··· 34 40 "web_accessible_resources": [ 35 41 { 36 42 "resources": ["index.js"], 37 - "matches": ["https://*.discord.com/*"] 43 + "matches": ["https://*.discord.com/*", "https://*.discordapp.com/*"] 38 44 } 39 45 ] 40 46 }
+12 -6
packages/browser/manifestv2.json
··· 1 1 { 2 + "$schema": "https://json.schemastore.org/chrome-manifest", 2 3 "manifest_version": 2, 3 4 "name": "moonlight", 4 5 "description": "Yet another Discord mod", 5 - "version": "1.3.0", 6 + "version": "1.3.14", 6 7 "permissions": [ 7 8 "webRequest", 8 9 "webRequestBlocking", 9 10 "scripting", 10 11 "webNavigation", 11 - "https://*.discord.com/assets/*.js", 12 + "https://*.discord.com/*", 13 + "https://*.discordapp.com/*", 12 14 "https://moonlight-mod.github.io/*", 13 - "https://api.github.com/*", 14 - "https://*.discord.com/*" 15 + "https://api.github.com/*" 15 16 ], 16 17 "background": { 17 18 "scripts": ["background.js"] ··· 19 20 "content_scripts": [ 20 21 { 21 22 "js": ["index.js"], 22 - "matches": ["https://*.discord.com/*"], 23 + "matches": ["https://*.discord.com/*", "https://*.discordapp.com/*"], 23 24 "run_at": "document_start", 24 25 "world": "MAIN" 25 26 } 26 - ] 27 + ], 28 + "browser_specific_settings": { 29 + "gecko": { 30 + "id": "{0fb6d66f-f22d-4555-a87b-34ef4bea5e2a}" 31 + } 32 + } 27 33 }
+12 -2
packages/browser/package.json
··· 1 1 { 2 2 "name": "@moonlight-mod/browser", 3 3 "private": true, 4 + "engines": { 5 + "node": ">=22", 6 + "pnpm": ">=10", 7 + "npm": "pnpm", 8 + "yarn": "pnpm" 9 + }, 4 10 "dependencies": { 5 11 "@moonlight-mod/core": "workspace:*", 6 12 "@moonlight-mod/types": "workspace:*", 7 13 "@moonlight-mod/web-preload": "workspace:*", 8 - "@zenfs/core": "^1.0.2", 9 - "@zenfs/dom": "^0.2.16" 14 + "@zenfs/core": "catalog:prod", 15 + "@zenfs/dom": "catalog:prod" 16 + }, 17 + "engineStrict": true, 18 + "devDependencies": { 19 + "@types/chrome": "catalog:dev" 10 20 } 11 21 }
+55 -70
packages/browser/src/background-mv2.js
··· 1 1 /* eslint-disable no-console */ 2 2 /* eslint-disable no-undef */ 3 3 4 - const starterUrls = ["web.", "sentry."]; 5 - let blockLoading = true; 6 - let doing = false; 7 - let collectedUrls = new Set(); 4 + const scriptUrls = ["web.", "sentry."]; 5 + let blockedScripts = new Set(); 8 6 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 - }); 7 + chrome.webRequest.onBeforeRequest.addListener( 8 + async (details) => { 9 + if (details.tabId === -1) return; 17 10 18 - async function doTheThing(urls, tabId) { 19 - console.log("Doing", urls, tabId); 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 20 21 - blockLoading = false; 21 + if (blockedScripts.size === scriptUrls.length) { 22 + const blockedScriptsCopy = Array.from(blockedScripts); 23 + blockedScripts.clear(); 22 24 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 - } 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 + } 34 38 35 - const scripts = [...document.querySelectorAll("script")].filter( 36 - (script) => script.src && urls.some((url) => url.includes(script.src)) 37 - ); 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 + ); 38 44 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); 45 + blockedScripts.reverse(); 46 + for (const url of blockedScripts) { 47 + if (url.includes("/sentry.")) continue; 44 48 45 - const newScript = document.createElement("script"); 46 - for (const { name, value } of script.attributes) { 47 - newScript.setAttribute(name, value); 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 + } 48 61 } 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); 62 + }); 63 + }, 0); 68 64 } 69 65 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 }; 66 + if (hasUrl) return { cancel: true }; 82 67 }, 83 68 { 84 - urls: ["https://*.discord.com/assets/*.js"] 69 + urls: ["https://*.discord.com/assets/*.js", "https://*.discordapp.com/assets/*.js"] 85 70 }, 86 71 ["blocking"] 87 72 ); ··· 94 79 ) 95 80 }; 96 81 }, 97 - { urls: ["https://*.discord.com/*"] }, 82 + { urls: ["https://*.discord.com/*", "https://*.discordapp.com/*"] }, 98 83 ["blocking", "responseHeaders"] 99 84 );
+37 -39
packages/browser/src/background.js
··· 1 1 /* eslint-disable no-console */ 2 2 /* eslint-disable no-undef */ 3 3 4 - const starterUrls = ["web.", "sentry."]; 5 - let blockLoading = true; 6 - let doing = false; 7 - let collectedUrls = new Set(); 4 + const scriptUrls = ["web.", "sentry."]; 5 + let blockedScripts = new Set(); 8 6 9 7 chrome.webNavigation.onBeforeNavigate.addListener(async (details) => { 10 8 const url = new URL(details.url); 11 - if (!blockLoading && url.hostname.endsWith("discord.com")) { 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"); 12 14 await chrome.declarativeNetRequest.updateEnabledRulesets({ 13 15 enableRulesetIds: ["modifyResponseHeaders", "blockLoading"] 14 16 }); 15 - blockLoading = true; 16 - collectedUrls.clear(); 17 17 } 18 18 }); 19 19 20 20 chrome.webRequest.onBeforeRequest.addListener( 21 21 async (details) => { 22 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 23 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); 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(); 34 38 35 39 console.log("Running moonlight script"); 36 40 try { ··· 40 44 files: ["index.js"] 41 45 }); 42 46 } catch (e) { 43 - console.log(e); 47 + console.error(e); 44 48 } 45 49 46 50 console.log("Initializing moonlight"); ··· 52 56 try { 53 57 await window._moonlightBrowserInit(); 54 58 } catch (e) { 55 - console.log(e); 59 + console.error(e); 56 60 } 57 61 } 58 62 }); ··· 60 64 console.log(e); 61 65 } 62 66 63 - console.log("Updating rulesets"); 67 + console.log("Disabling block ruleset"); 64 68 try { 65 - blockLoading = false; 66 69 await chrome.declarativeNetRequest.updateEnabledRulesets({ 67 70 disableRulesetIds: ["blockLoading"], 68 71 enableRulesetIds: ["modifyResponseHeaders"] 69 72 }); 70 73 } catch (e) { 71 - console.log(e); 74 + console.error(e); 72 75 } 73 76 74 77 console.log("Readding scripts"); ··· 76 79 await chrome.scripting.executeScript({ 77 80 target: { tabId: details.tabId }, 78 81 world: "MAIN", 79 - args: [urls], 80 - func: async (urls) => { 82 + args: [blockedScriptsCopy], 83 + func: async (blockedScripts) => { 81 84 const scripts = [...document.querySelectorAll("script")].filter( 82 - (script) => script.src && urls.some((url) => url.includes(script.src)) 85 + (script) => script.src && blockedScripts.some((url) => url.includes(script.src)) 83 86 ); 84 87 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); 88 + blockedScripts.reverse(); 89 + for (const url of blockedScripts) { 90 + if (url.includes("/sentry.")) continue; 90 91 92 + const script = scripts.find((script) => url.includes(script.src)); 91 93 const newScript = document.createElement("script"); 92 - for (const { name, value } of script.attributes) { 93 - newScript.setAttribute(name, value); 94 + for (const attr of script.attributes) { 95 + if (attr.name === "src") attr.value += "?inj"; 96 + newScript.setAttribute(attr.name, attr.value); 94 97 } 95 - 96 98 script.remove(); 97 99 document.documentElement.appendChild(newScript); 98 100 } 99 101 } 100 102 }); 101 103 } catch (e) { 102 - console.log(e); 104 + console.error(e); 103 105 } 104 - 105 - console.log("Done"); 106 - doing = false; 107 - collectedUrls.clear(); 108 106 } 109 107 }, 110 108 { 111 - urls: ["*://*.discord.com/assets/*.js"] 109 + urls: ["*://*.discord.com/assets/*.js", "*://*.discordapp.com/assets/*.js"] 112 110 } 113 111 );
+14 -12
packages/browser/src/index.ts
··· 6 6 import { MoonlightBranch, MoonlightNode } from "@moonlight-mod/types"; 7 7 import { getConfig, getConfigOption, getManifest, setConfigOption } from "@moonlight-mod/core/util/config"; 8 8 import { IndexedDB } from "@zenfs/dom"; 9 - import { configure } from "@zenfs/core"; 9 + import { configureSingle } from "@zenfs/core"; 10 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"; 11 13 12 14 function getParts(path: string) { 13 15 if (path.startsWith("/")) path = path.substring(1); ··· 18 20 delete window._moonlightBrowserInit; 19 21 20 22 // 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 - } 23 + await configureSingle({ 24 + backend: IndexedDB, 25 + storeName: "moonlight-fs" 30 26 }); 31 27 32 28 window.moonlightNodeSandboxed = { ··· 94 90 dirname(path) { 95 91 const parts = getParts(path); 96 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 97 } 98 98 }, 99 99 // TODO ··· 116 116 processedExtensions, 117 117 nativesCache: {}, 118 118 isBrowser: true, 119 + events: createEventEmitter<NodeEventType, NodeEventPayloads>(), 119 120 120 121 version: MOONLIGHT_VERSION, 121 122 branch: MOONLIGHT_BRANCH as MoonlightBranch, ··· 127 128 const manifest = getManifest(extensions, ext); 128 129 return getConfigOption(ext, name, config, manifest?.settings); 129 130 }, 130 - setConfigOption(ext, name, value) { 131 + async setConfigOption(ext, name, value) { 131 132 setConfigOption(config, ext, name, value); 132 - this.writeConfig(config); 133 + await this.writeConfig(config); 133 134 }, 134 135 135 136 getNatives: () => {}, ··· 147 148 async writeConfig(newConfig) { 148 149 await writeConfig(newConfig); 149 150 config = newConfig; 151 + this.events.dispatchEvent(NodeEventType.ConfigSaved, newConfig); 150 152 } 151 153 }; 152 154
+1
packages/browser/tsconfig.json
··· 1 1 { 2 2 "extends": "../../tsconfig.json", 3 3 "compilerOptions": { 4 + "lib": ["DOM", "ESNext", "ESNext.AsyncIterable"], 4 5 "module": "ES2022" 5 6 } 6 7 }
+7
packages/core/package.json
··· 4 4 "exports": { 5 5 "./*": "./src/*.ts" 6 6 }, 7 + "engineStrict": true, 8 + "engines": { 9 + "node": ">=22", 10 + "pnpm": ">=10", 11 + "npm": "pnpm", 12 + "yarn": "pnpm" 13 + }, 7 14 "dependencies": { 8 15 "@moonlight-mod/types": "workspace:*" 9 16 }
+5 -5
packages/core/src/extension/loader.ts
··· 13 13 import calculateDependencies from "../util/dependency"; 14 14 import { createEventEmitter } from "../util/event"; 15 15 import { registerStyles } from "../styles"; 16 - import { EventPayloads, EventType } from "@moonlight-mod/types/core/event"; 16 + import { WebEventPayloads, WebEventType } from "@moonlight-mod/types/core/event"; 17 17 18 18 const logger = new Logger("core/extension/loader"); 19 19 ··· 202 202 } 203 203 204 204 export async function loadProcessedExtensions({ extensions, dependencyGraph }: ProcessedExtensions) { 205 - const eventEmitter = createEventEmitter<EventType, EventPayloads>(); 205 + const eventEmitter = createEventEmitter<WebEventType, WebEventPayloads>(); 206 206 const finished: Set<string> = new Set(); 207 207 208 208 logger.trace( ··· 224 224 } 225 225 226 226 function done() { 227 - eventEmitter.removeEventListener(EventType.ExtensionLoad, cb); 227 + eventEmitter.removeEventListener(WebEventType.ExtensionLoad, cb); 228 228 r(); 229 229 } 230 230 231 - eventEmitter.addEventListener(EventType.ExtensionLoad, cb); 231 + eventEmitter.addEventListener(WebEventType.ExtensionLoad, cb); 232 232 if (finished.has(dep)) done(); 233 233 }) 234 234 ); ··· 242 242 await loadExt(ext); 243 243 244 244 finished.add(ext.id); 245 - eventEmitter.dispatchEvent(EventType.ExtensionLoad, ext.id); 245 + eventEmitter.dispatchEvent(WebEventType.ExtensionLoad, ext.id); 246 246 logger.debug(`Loaded "${ext.id}"`); 247 247 } 248 248
+1 -4
packages/core/src/extension.ts
··· 129 129 const ret: DetectedExtension[] = []; 130 130 const seen = new Set<string>(); 131 131 132 - const coreExtensionsFs: Record<string, string> = JSON.parse( 133 - // @ts-expect-error shut up 134 - _moonlight_coreExtensionsStr 135 - ); 132 + const coreExtensionsFs: Record<string, string> = JSON.parse(_moonlight_coreExtensionsStr); 136 133 const coreExtensions = Array.from(new Set(Object.keys(coreExtensionsFs).map((x) => x.split("/")[0]))); 137 134 138 135 for (const ext of coreExtensions) {
+3
packages/core/src/fs.ts
··· 48 48 }, 49 49 dirname(dir) { 50 50 return path.dirname(dir); 51 + }, 52 + basename(dir) { 53 + return path.basename(dir); 51 54 } 52 55 }; 53 56 }
+57 -33
packages/core/src/patch.ts
··· 11 11 } from "@moonlight-mod/types"; 12 12 import Logger from "./util/logger"; 13 13 import calculateDependencies, { Dependency } from "./util/dependency"; 14 - import { EventType } from "@moonlight-mod/types/core/event"; 14 + import { WebEventType } from "@moonlight-mod/types/core/event"; 15 15 import { processFind, processReplace, testFind } from "./util/patch"; 16 16 17 17 const logger = new Logger("core/patch"); ··· 66 66 const moduleCache: Record<string, string> = {}; 67 67 const patched: Record<string, Array<string>> = {}; 68 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); 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 + } 74 75 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(", "); 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(", "); 78 87 79 - const wrapped = 80 - `(${replaced}).apply(this, arguments)\n` + 81 - `// Patched by moonlight: ${patchedStr}\n` + 82 - `//# sourceURL=Webpack-Module-${id}`; 88 + const wrapped = 89 + `(${replaced}).apply(this, arguments)\n` + `// Patched by moonlight: ${patchedStr}\n` + createSourceURL(id); 83 90 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 - } 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; 94 100 } 101 + } 95 102 103 + function patchModules(entry: WebpackJsonpEntry[1]) { 96 104 // Populate the module cache 97 105 for (const [id, func] of Object.entries(entry)) { 98 106 if (!Object.hasOwn(moduleCache, id) && func.__moonlight !== true) { ··· 108 116 const origModuleString = moduleCache[id]; 109 117 let moduleString = origModuleString; 110 118 const patchedStr = []; 111 - const mappedName = moonlight.moonmap.modules[id]; 119 + const mappedName = Object.entries(moonlight.moonmap.modules).find((m) => m[1] === id)?.[0]; 112 120 let modified = false; 121 + let swappedModule = false; 113 122 114 123 const exts = new Set<string>(); 115 124 116 125 for (let i = 0; i < patches.length; i++) { 117 126 const patch = patches[i]; 118 127 if (patch.prerequisite != null && !patch.prerequisite()) { 128 + moonlight.unpatched.delete(patch); 119 129 continue; 120 130 } 121 131 ··· 135 145 // We ensured normal PatchReplace objects get turned into arrays on register 136 146 const replaces = patch.replace as PatchReplace[]; 137 147 148 + let isPatched = true; 138 149 for (let i = 0; i < replaces.length; i++) { 139 150 const replace = replaces[i]; 140 151 let patchId = `${patch.ext}#${patch.id}`; ··· 151 162 } 152 163 153 164 if (replaced === moduleString) { 154 - logger.warn("Patch replacement failed", id, patch); 165 + logger.warn("Patch replacement failed", id, patchId, patch); 166 + isPatched = false; 155 167 if (patch.hardFail) { 156 168 hardFailed = true; 157 169 break; ··· 164 176 const newModule = replace.replacement(replaced); 165 177 entry[id] = newModule; 166 178 entry[id].__moonlight = true; 167 - replaced = replaced.toString().replace(/\n/g, "") + `//# sourceURL=Webpack-Module-${id}`; 179 + replaced = newModule.toString().replace(/\n/g, ""); 180 + swappedModule = true; 168 181 } 169 182 } 170 183 ··· 174 187 exts.add(patch.ext); 175 188 } 176 189 177 - moonlight.unpatched.delete(patch); 190 + if (isPatched) moonlight.unpatched.delete(patch); 178 191 if (shouldRemove) patches.splice(i--, 1); 179 192 } 180 193 } 181 194 182 195 if (modified) { 183 - patchModule(id, patchedStr.join(", "), moduleString); 184 - moduleCache[id] = moduleString; 196 + let shouldCache = true; 197 + if (!swappedModule) shouldCache = patchModule(id, patchedStr.join(", "), moduleString, entry); 198 + if (shouldCache) moduleCache[id] = moduleString; 185 199 moonlight.patched.set(id, exts); 186 200 } 187 201 ··· 189 203 const parsed = moonlight.lunast.parseScript(id, moduleString); 190 204 if (parsed != null) { 191 205 for (const [parsedId, parsedScript] of Object.entries(parsed)) { 192 - if (patchModule(parsedId, "lunast", parsedScript)) { 206 + if (patchModule(parsedId, "lunast", parsedScript, entry)) { 193 207 moduleCache[parsedId] = parsedScript; 194 208 } 195 209 } ··· 200 214 201 215 if (moonlightNode.config.patchAll === true) { 202 216 if ((typeof id !== "string" || !id.includes("_")) && !entry[id].__moonlight) { 203 - const wrapped = `(${moduleCache[id]}).apply(this, arguments)\n` + `//# sourceURL=Webpack-Module-${id}`; 217 + const wrapped = `(${moduleCache[id]}).apply(this, arguments)\n` + createSourceURL(id); 204 218 entry[id] = new Function("module", "exports", "require", wrapped) as WebpackModuleFunc; 205 219 entry[id].__moonlight = true; 206 220 } ··· 308 322 if (wpModule.run) { 309 323 modules[id] = wpModule.run; 310 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 + }; 311 333 if (wpModule.entrypoint) entrypoints.push(id); 312 334 } 313 335 } ··· 315 337 } 316 338 317 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; 318 342 injectedWpModules.push({ id: name, run: func }); 319 343 modules[name] = func; 320 344 inject = true; ··· 392 416 const realPush = jsonp.push; 393 417 if (jsonp.push.__moonlight !== true) { 394 418 jsonp.push = (items) => { 395 - moonlight.events.dispatchEvent(EventType.ChunkLoad, { 419 + moonlight.events.dispatchEvent(WebEventType.ChunkLoad, { 396 420 chunkId: items[0], 397 421 modules: items[1], 398 422 require: items[2] ··· 440 464 set(modules: any) { 441 465 const { stack } = new Error(); 442 466 if (stack!.includes("/assets/") && !Array.isArray(modules)) { 443 - moonlight.events.dispatchEvent(EventType.ChunkLoad, { 467 + moonlight.events.dispatchEvent(WebEventType.ChunkLoad, { 444 468 modules: modules 445 469 }); 446 470 patchModules(modules);
+4 -1
packages/core/tsconfig.json
··· 1 1 { 2 - "extends": "../../tsconfig.json" 2 + "extends": "../../tsconfig.json", 3 + "compilerOptions": { 4 + "lib": ["ESNext", "DOM"] 5 + } 3 6 }
+9 -2
packages/core-extensions/package.json
··· 1 1 { 2 2 "name": "@moonlight-mod/core-extensions", 3 3 "private": true, 4 + "engineStrict": true, 5 + "engines": { 6 + "node": ">=22", 7 + "pnpm": ">=10", 8 + "npm": "pnpm", 9 + "yarn": "pnpm" 10 + }, 4 11 "dependencies": { 5 12 "@moonlight-mod/core": "workspace:*", 6 13 "@moonlight-mod/types": "workspace:*", 7 - "microdiff": "^1.5.0", 8 - "nanotar": "^0.1.1" 14 + "microdiff": "catalog:prod", 15 + "nanotar": "catalog:prod" 9 16 } 10 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 2 3 3 export const webpackModules: ExtensionWebExports["webpackModules"] = { 4 4 stores: { 5 - dependencies: [ 6 - { 7 - id: "discord/packages/flux" 8 - } 9 - ] 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" }] 10 12 } 11 13 };
+1 -1
packages/core-extensions/src/common/manifest.json
··· 4 4 "apiLevel": 2, 5 5 "meta": { 6 6 "name": "Common", 7 - "tagline": "A *lot* of common clientmodding utilities from the Discord client", 7 + "tagline": "Common client modding utilities for the Discord client", 8 8 "authors": ["Cynosphere", "NotNite"], 9 9 "tags": ["library"] 10 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;
+9 -4
packages/core-extensions/src/contextMenu/webpackModules/contextMenu.ts
··· 11 11 type Patch = { 12 12 navId: string; 13 13 item: React.FC<any>; 14 - anchorId: string; 14 + anchor: string | RegExp; 15 15 before: boolean; 16 16 }; 17 17 18 - function addItem<T = any>(navId: string, item: React.FC<T>, anchorId: string, before = false) { 19 - patches.push({ navId, item, anchorId, before }); 18 + function addItem<T = any>(navId: string, item: React.FC<T>, anchor: string | RegExp, before = false) { 19 + if (anchor instanceof RegExp && anchor.flags.includes("g")) 20 + throw new Error("anchor regular expression should not be global"); 21 + patches.push({ navId, item, anchor, before }); 20 22 } 21 23 22 24 const patches: Patch[] = []; ··· 25 27 if (!matches.length) return items; 26 28 27 29 for (const patch of matches) { 28 - const idx = items.findIndex((i) => i.key === patch.anchorId); 30 + const idx = items.findIndex((i) => 31 + typeof patch.anchor === "string" ? i.key === patch.anchor : patch.anchor.test(i.key!) 32 + ); 29 33 if (idx === -1) continue; 30 34 items.splice(idx + 1 - +patch.before, 0, ...parser(patch.item(menuProps) as ReturnType)); 31 35 } ··· 54 58 }; 55 59 56 60 // Unmangle Menu elements 61 + // spacepack.require.m[moonlight.moonmap.modules["discord/modules/menus/web/Menu"]].toString(); 57 62 const code = 58 63 spacepack.require.m[ 59 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 1 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 2 2 3 + // spacepack.require.m[moonlight.moonmap.modules["discord/modules/menus/web/Menu"]].toString(); 3 4 let code = 4 5 spacepack.require.m[ 5 6 spacepack.findByCode("Menu API only allows Items and groups of Items as children.")[0].id ··· 7 8 8 9 const parserSym = code.match(/(?<=_patchMenu\(.,).+?(?=\()/)![0]; 9 10 10 - code = code.replace(/(?<=function\(\){return ).(?=})/, parserSym); 11 + code = code.replace(/{(.):\(\)=>./, (orig, e) => `{${e}:()=>${parserSym}`); 11 12 const mod = new Function("module", "exports", "require", `(${code}).apply(this, arguments)`); 12 13 13 14 const exp: any = {};
+2 -2
packages/core-extensions/src/disableSentry/index.ts
··· 6 6 find: "profiledRootComponent:", 7 7 replace: { 8 8 type: PatchReplaceType.Normal, 9 - match: /(?<=\.Z=){.+?}}/, 10 - replacement: 'require("disableSentry_stub").proxy()' 9 + match: /Z:\(\)=>\i/, 10 + replacement: 'Z:()=>require("disableSentry_stub").proxy()' 11 11 } 12 12 }, 13 13 {
+4 -1
packages/core-extensions/src/disableSentry/manifest.json
··· 12 12 "https://*.sentry.io/*", 13 13 "https://*.discord.com/error-reporting-proxy/*", 14 14 "https://discord.com/assets/sentry.*.js", 15 - "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" 16 19 ] 17 20 }
+23 -6
packages/core-extensions/src/experiments/index.ts
··· 11 11 { 12 12 find: '"scientist:triggered"', // Scientist? Triggered. 13 13 replace: { 14 - match: /(?<=personal_connection_id\|\|)!1/, 15 - replacement: "!0" 14 + match: ".personal_connection_id", 15 + replacement: ".personal_connection_id || true" 16 16 } 17 17 }, 18 18 ··· 20 20 { 21 21 find: ".HEADER_BAR)", 22 22 replace: { 23 - match: /&&\((.)\?\(0,/, 23 + match: /&&\((\i)\?\(0,/, 24 24 replacement: (_, isStaff) => 25 25 `&&(((moonlight.getConfigOption("experiments","devtools")??false)?true:${isStaff})?(0,` 26 26 } 27 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 + }, 28 45 29 46 // Enable further staff-locked options 30 47 { 31 48 find: "shouldShowLurkerModeUpsellPopout:", 32 49 replace: { 33 - match: /\.useReducedMotion,isStaff:(.),/, 34 - replacement: (_, isStaff) => 35 - `.useReducedMotion,isStaff:(moonlight.getConfigOption("experiments","staffSettings")??false)?true:${isStaff},` 50 + match: /\.useReducedMotion,isStaff:(\i)(,|})/, 51 + replacement: (_, isStaff, trail) => 52 + `.useReducedMotion,isStaff:(moonlight.getConfigOption("experiments","staffSettings")??false)?true:${isStaff}${trail}` 36 53 } 37 54 } 38 55 ];
+38 -7
packages/core-extensions/src/moonbase/host.ts
··· 2 2 import * as fs from "node:fs/promises"; 3 3 import * as path from "node:path"; 4 4 import getNatives from "./native"; 5 + import { MoonlightBranch } from "@moonlight-mod/types"; 5 6 6 7 const natives = getNatives(); 7 8 ··· 50 51 electron.app.exit(0); 51 52 } 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 + 53 67 function showAbout() { 54 68 electron.dialog.showMessageBox({ 55 69 title: "About moonlight", ··· 63 77 const i = entries.findIndex((e) => e.label === "Check for Updates..."); 64 78 if (i === -1) return original.call(this, entries); 65 79 66 - entries.splice(i + 1, 0, { 67 - label: "moonlight", 68 - submenu: [ 80 + if (!entries.find((e) => e.label === "moonlight")) { 81 + const options: Electron.MenuItemConstructorOptions[] = [ 69 82 { label: "Update and restart", click: updateAndRestart }, 70 - { label: "Reset config", click: resetConfig }, 71 - { label: "About", click: showAbout } 72 - ] 73 - }); 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 + } 74 105 75 106 return original.call(this, entries); 76 107 };
+15 -5
packages/core-extensions/src/moonbase/index.tsx
··· 8 8 { 9 9 // CvQlAA mapped to ERRORS_ACTION_TO_TAKE 10 10 // FIXME: Better patch find? 11 - match: /,(\(0,(.)\.jsx\))\("p",{children:.\.intl\.string\(.\..\.CvQlAA\)}\)/, 11 + match: /,(\(0,(\i)\.jsx\))\("p",{children:\i\.\i\.string\(\i\.\i\.CvQlAA\)}\)/, 12 12 replacement: (_, createElement, ReactJSX) => 13 13 `,${createElement}(require("moonbase_crashScreen")?.UpdateText??${ReactJSX}.Fragment,{state:this.state,setState:this.setState.bind(this)})` 14 14 }, 15 15 16 16 // wrap actions field to display error details 17 17 { 18 - match: /(?<=return(\(0,(.)\.jsx\))\(.+?,)action:(.),className:/, 18 + match: /(?<=return(\(0,(\i)\.jsx\))\(.+?,)action:(\i),className:/, 19 19 replacement: (_, createElement, ReactJSX, action) => 20 20 `action:require("moonbase_crashScreen")?.wrapAction?${createElement}(require("moonbase_crashScreen").wrapAction,{action:${action},state:this.state}):${action},className:` 21 21 }, ··· 23 23 // add update button 24 24 // +hivLS -> ERRORS_RELOAD 25 25 { 26 - match: /(?<=\["\+hivLS"\]\)}\),(\(0,(.)\.jsx\))\(.,{}\))/, 26 + match: /(?<=\["\+hivLS"\]\)}\),(\(0,(\i)\.jsx\))\(\i,{}\))/, 27 27 replacement: (_, createElement, ReactJSX) => 28 28 `,${createElement}(require("moonbase_crashScreen")?.UpdateButton??${ReactJSX}.Fragment,{state:this.state,setState:this.setState.bind(this)})` 29 29 } ··· 42 42 { id: "react" }, 43 43 { id: "discord/components/common/index" }, 44 44 { ext: "moonbase", id: "stores" }, 45 - { id: "discord/modules/guild_settings/IntegrationCard.css" }, 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" }, 46 49 "Masks.PANEL_BUTTON", 47 50 '"Missing channel in Channel.openChannelContextMenu"', 48 51 ".forumOrHome]:" 49 52 ] 53 + }, 54 + 55 + ThemeDarkIcon: { 56 + dependencies: [{ ext: "common", id: "icons" }, { id: "react" }] 50 57 }, 51 58 52 59 settings: { ··· 54 61 { ext: "spacepack", id: "spacepack" }, 55 62 { ext: "settings", id: "settings" }, 56 63 { id: "react" }, 57 - { ext: "moonbase", id: "ui" } 64 + { ext: "moonbase", id: "ui" }, 65 + { ext: "contextMenu", id: "contextMenu" }, 66 + ':"USER_SETTINGS_MODAL_SET_SECTION"' 58 67 ], 59 68 entrypoint: true 60 69 }, ··· 63 72 dependencies: [ 64 73 { id: "react" }, 65 74 { ext: "moonbase", id: "stores" }, 75 + { ext: "moonbase", id: "ThemeDarkIcon" }, 66 76 { ext: "notices", id: "notices" }, 67 77 { 68 78 ext: "spacepack",
+11 -3
packages/core-extensions/src/moonbase/manifest.json
··· 7 7 "tagline": "The official settings UI for moonlight", 8 8 "authors": ["Cynosphere", "NotNite", "redstonekasi"] 9 9 }, 10 - "dependencies": ["spacepack", "settings", "common", "notices"], 10 + "dependencies": ["spacepack", "settings", "common", "notices", "contextMenu"], 11 11 "settings": { 12 12 "sections": { 13 13 "advice": "reload", 14 14 "displayName": "Split into sections", 15 15 "description": "Show the Moonbase tabs as separate sections", 16 - "type": "boolean" 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 17 24 }, 18 25 "saveFilter": { 19 26 "advice": "none", 20 27 "displayName": "Persist filter", 21 28 "description": "Save extension filter in config", 22 - "type": "boolean" 29 + "type": "boolean", 30 + "default": false 23 31 }, 24 32 "updateChecking": { 25 33 "advice": "none",
+17 -24
packages/core-extensions/src/moonbase/native.ts
··· 15 15 16 16 export const userAgent = `moonlight/${moonlightGlobal.version} (https://github.com/moonlight-mod/moonlight)`; 17 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 + 18 23 async function getStableRelease(): Promise<{ 19 24 name: string; 20 25 assets: { ··· 24 29 }> { 25 30 const req = await fetch(githubApiUrl, { 26 31 cache: "no-store", 27 - headers: { 28 - "User-Agent": userAgent 29 - } 32 + headers: sharedHeaders 30 33 }); 31 34 return await req.json(); 32 35 } ··· 43 46 } else if (moonlightGlobal.branch === MoonlightBranch.NIGHTLY) { 44 47 const req = await fetch(nightlyRefUrl, { 45 48 cache: "no-store", 46 - headers: { 47 - "User-Agent": userAgent 48 - } 49 + headers: sharedHeaders 49 50 }); 50 51 const ref = (await req.text()).split("\n")[0]; 51 52 return ref !== moonlightGlobal.version ? ref : null; ··· 58 59 } 59 60 }, 60 61 61 - async updateMoonlight() { 62 + async updateMoonlight(overrideBranch?: MoonlightBranch) { 63 + const branch = overrideBranch ?? moonlightGlobal.branch; 64 + 62 65 // Note: this won't do anything on browser, we should probably disable it 63 66 // entirely when running in browser. 64 67 async function downloadStable(): Promise<[ArrayBuffer, string]> { ··· 69 72 logger.debug(`Downloading ${asset.browser_download_url}`); 70 73 const req = await fetch(asset.browser_download_url, { 71 74 cache: "no-store", 72 - headers: { 73 - "User-Agent": userAgent 74 - } 75 + headers: sharedHeaders 75 76 }); 76 77 77 78 return [await req.arrayBuffer(), json.name]; ··· 81 82 logger.debug(`Downloading ${nightlyZipUrl}`); 82 83 const zipReq = await fetch(nightlyZipUrl, { 83 84 cache: "no-store", 84 - headers: { 85 - "User-Agent": userAgent 86 - } 85 + headers: sharedHeaders 87 86 }); 88 87 89 88 const refReq = await fetch(nightlyRefUrl, { 90 89 cache: "no-store", 91 - headers: { 92 - "User-Agent": userAgent 93 - } 90 + headers: sharedHeaders 94 91 }); 95 92 const ref = (await refReq.text()).split("\n")[0]; 96 93 ··· 98 95 } 99 96 100 97 const [tar, ref] = 101 - moonlightGlobal.branch === MoonlightBranch.STABLE 98 + branch === MoonlightBranch.STABLE 102 99 ? await downloadStable() 103 - : moonlightGlobal.branch === MoonlightBranch.NIGHTLY 100 + : branch === MoonlightBranch.NIGHTLY 104 101 ? await downloadNightly() 105 102 : [null, null]; 106 103 ··· 137 134 try { 138 135 const req = await fetch(repo, { 139 136 cache: "no-store", 140 - headers: { 141 - "User-Agent": userAgent 142 - } 137 + headers: sharedHeaders 143 138 }); 144 139 const json = await req.json(); 145 140 ret[repo] = json; ··· 154 149 async installExtension(manifest, url, repo) { 155 150 const req = await fetch(url, { 156 151 cache: "no-store", 157 - headers: { 158 - "User-Agent": userAgent 159 - } 152 + headers: sharedHeaders 160 153 }); 161 154 162 155 const dir = moonlightGlobal.getExtensionDir(manifest.id);
+63
packages/core-extensions/src/moonbase/style.css
··· 16 16 resize: vertical; 17 17 } 18 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 + 19 40 /* Update notice at the top of the client */ 20 41 .moonbase-updates-notice { 21 42 background-color: var(--moonbase-bg); ··· 73 94 display: flex; 74 95 flex-direction: row; 75 96 gap: 8px; 97 + align-items: center; 76 98 } 77 99 78 100 .moonbase-update-divider { 79 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)); 80 113 } 81 114 82 115 /* Crash screen */ ··· 204 237 line-height: 1.286; 205 238 font-weight: 400; 206 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 1 import { ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 2 - import { DetectedExtension, ExtensionManifest } from "@moonlight-mod/types"; 2 + import { DetectedExtension, ExtensionManifest, MoonlightBranch } from "@moonlight-mod/types"; 3 3 4 4 export type MoonbaseNatives = { 5 5 checkForMoonlightUpdate(): Promise<string | null>; 6 - updateMoonlight(): Promise<void>; 6 + updateMoonlight(overrideBranch?: MoonlightBranch): Promise<void>; 7 7 8 8 fetchRepositories(repos: string[]): Promise<Record<string, RepositoryManifest[]>>; 9 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 1 import React from "@moonlight-mod/wp/react"; 2 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 2 + import { Button, TabBar } from "@moonlight-mod/wp/discord/components/common/index"; 3 3 import { useStateFromStores, useStateFromStoresObject } from "@moonlight-mod/wp/discord/packages/flux"; 4 - import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 5 4 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 6 5 import { RepositoryManifest, UpdateState } from "../types"; 7 6 import { ConfigExtension, DetectedExtension } from "@moonlight-mod/types"; 7 + import DiscoveryClasses from "@moonlight-mod/wp/discord/modules/discovery/web/Discovery.css"; 8 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; 9 + const MODULE_REGEX = /Webpack-Module\/(\d+)\/(\d+)/g; 13 10 14 11 const logger = moonlight.getLogger("moonbase/crashScreen"); 15 12 ··· 87 84 } 88 85 89 86 function ExtensionDisableCard({ ext }: { ext: DetectedExtension }) { 90 - function disableWithDependents() { 87 + async function disableWithDependents() { 91 88 const disable = new Set<string>(); 92 89 disable.add(ext.id); 93 90 for (const [id, dependencies] of moonlightNode.processedExtensions.dependencyGraph) { ··· 108 105 msg += "?"; 109 106 110 107 if (confirm(msg)) { 111 - moonlightNode.writeConfig(config); 108 + await moonlightNode.writeConfig(config); 112 109 window.location.reload(); 113 110 } 114 111 } ··· 142 139 const causes = React.useMemo(() => { 143 140 const causes = new Set<string>(); 144 141 if (state.error.stack) { 145 - for (const [, id] of state.error.stack.matchAll(MODULE_REGEX)) 142 + for (const [, , id] of state.error.stack.matchAll(MODULE_REGEX)) 146 143 for (const ext of moonlight.patched.get(id) ?? []) causes.add(ext); 147 144 } 148 - for (const [, id] of state.info.componentStack.matchAll(MODULE_REGEX)) 145 + for (const [, , id] of state.info.componentStack.matchAll(MODULE_REGEX)) 149 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 + 150 163 return [...causes]; 151 164 }, []); 152 165 ··· 154 167 <div className="moonbase-crash-wrapper"> 155 168 {action} 156 169 <TabBar 157 - className={`${TabBarClasses.tabBar} moonbase-crash-tabs`} 170 + className={`${DiscoveryClasses.tabBar} moonbase-crash-tabs`} 158 171 type="top" 159 172 selectedItem={tab} 160 173 onItemSelect={(v) => setTab(v)} 161 174 > 162 - <TabBar.Item className={TabBarClasses.tabBarItem} id="crash"> 175 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id="crash"> 163 176 Crash details 164 177 </TabBar.Item> 165 - <TabBar.Item className={TabBarClasses.tabBarItem} id="extensions" disabled={updateCount === 0}> 178 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id="extensions" disabled={updateCount === 0}> 166 179 {`Extension updates (${updateCount})`} 167 180 </TabBar.Item> 168 - <TabBar.Item className={TabBarClasses.tabBarItem} id="causes" disabled={causes.length === 0}> 181 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id="causes" disabled={causes.length === 0}> 169 182 {`Possible causes (${causes.length})`} 170 183 </TabBar.Item> 171 184 </TabBar>
+27 -17
packages/core-extensions/src/moonbase/webpackModules/settings.tsx
··· 2 2 import React from "@moonlight-mod/wp/react"; 3 3 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 4 4 import { Moonbase, pages, RestartAdviceMessage, Update } from "@moonlight-mod/wp/moonbase_ui"; 5 - 5 + import UserSettingsModalActionCreators from "@moonlight-mod/wp/discord/actions/UserSettingsModalActionCreators"; 6 + import Margins from "@moonlight-mod/wp/discord/styles/shared/Margins.css"; 6 7 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.findByExports("setSection", "clearSubsection")[0].exports.Z; 8 + import { Text, Breadcrumbs } from "@moonlight-mod/wp/discord/components/common/index"; 9 + import { MenuItem } from "@moonlight-mod/wp/contextMenu_contextMenu"; 14 10 15 - let SettingsNotice; 16 11 const notice = { 17 12 stores: [MoonbaseSettingsStore], 18 13 element: () => { 19 14 // Require it here because lazy loading SUX 20 - SettingsNotice ??= spacepack.findByCode("onSaveButtonColor", "FocusRingScope")[0].exports.Z; 15 + const SettingsNotice = spacepack.require("discord/components/common/SettingsNotice").default; 21 16 return ( 22 17 <SettingsNotice 23 18 submitting={MoonbaseSettingsStore.submitting} 24 19 onReset={() => { 25 20 MoonbaseSettingsStore.reset(); 26 21 }} 27 - onSave={() => { 28 - MoonbaseSettingsStore.writeConfig(); 22 + onSave={async () => { 23 + await MoonbaseSettingsStore.writeConfig(); 29 24 }} 30 25 /> 31 26 ); 32 27 } 33 28 }; 29 + 30 + const oldLocation = MoonbaseSettingsStore.getExtensionConfigRaw<boolean>("moonbase", "oldLocation", false); 31 + const position = oldLocation ? -2 : -9999; 34 32 35 33 function addSection(id: string, name: string, element: React.FunctionComponent) { 36 - settings.addSection(`moonbase-${id}`, name, element, null, -2, notice); 34 + settings.addSection(`moonbase-${id}`, name, element, null, position, notice); 37 35 } 38 36 39 37 // FIXME: move to component types ··· 50 48 ); 51 49 } 52 50 51 + if (!oldLocation) { 52 + settings.addDivider(position); 53 + } 54 + 53 55 if (MoonbaseSettingsStore.getExtensionConfigRaw<boolean>("moonbase", "sections", false)) { 54 - settings.addHeader("Moonbase", -2); 56 + if (oldLocation) settings.addHeader("Moonbase", position); 55 57 56 - for (const page of pages) { 58 + const _pages = oldLocation ? pages : pages.reverse(); 59 + for (const page of _pages) { 57 60 addSection(page.id, page.name, () => { 58 61 const breadcrumbs = [ 59 62 { id: "moonbase", label: "Moonbase" }, ··· 78 81 ); 79 82 }); 80 83 } 84 + 85 + if (!oldLocation) settings.addHeader("Moonbase", position); 81 86 } else { 82 - settings.addSection("moonbase", "Moonbase", Moonbase, null, -2, notice); 87 + settings.addSection("moonbase", "Moonbase", Moonbase, null, position, notice); 83 88 84 89 settings.addSectionMenuItems( 85 90 "moonbase", 86 91 ...pages.map((page, i) => ( 87 - <MenuItem key={page.id} id={`moonbase-${page.id}`} label={page.name} action={() => open("moonbase", i)} /> 92 + <MenuItem 93 + key={page.id} 94 + id={`moonbase-${page.id}`} 95 + label={page.name} 96 + action={() => UserSettingsModalActionCreators.open("moonbase", i.toString())} 97 + /> 88 98 )) 89 99 ); 90 100 }
+84 -23
packages/core-extensions/src/moonbase/webpackModules/stores.ts
··· 1 1 import { Config, ExtensionEnvironment, ExtensionLoadSource, ExtensionSettingsAdvice } from "@moonlight-mod/types"; 2 - import { ExtensionState, MoonbaseExtension, MoonbaseNatives, RepositoryManifest, RestartAdvice } from "../types"; 2 + import { 3 + ExtensionState, 4 + MoonbaseExtension, 5 + MoonbaseNatives, 6 + RepositoryManifest, 7 + RestartAdvice, 8 + UpdateState 9 + } from "../types"; 3 10 import { Store } from "@moonlight-mod/wp/discord/packages/flux"; 4 11 import Dispatcher from "@moonlight-mod/wp/discord/Dispatcher"; 5 12 import getNatives from "../native"; 6 13 import { mainRepo } from "@moonlight-mod/types/constants"; 7 14 import { checkExtensionCompat, ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 8 15 import { CustomComponent } from "@moonlight-mod/types/coreExtensions/moonbase"; 16 + import { NodeEventType } from "@moonlight-mod/types/core/event"; 9 17 import { getConfigOption, setConfigOption } from "@moonlight-mod/core/util/config"; 10 18 import diff from "microdiff"; 11 19 ··· 25 33 submitting: boolean; 26 34 installing: boolean; 27 35 36 + #updateState = UpdateState.Ready; 37 + get updateState() { 38 + return this.#updateState; 39 + } 28 40 newVersion: string | null; 29 41 shouldShowNotice: boolean; 30 42 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 43 restartAdvice = RestartAdvice.NotNeeded; 41 44 42 45 extensions: { [id: number]: MoonbaseExtension }; ··· 76 79 }; 77 80 } 78 81 82 + // This is async but we're calling it without 79 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 + }); 80 93 } 81 94 82 95 async checkUpdates() { ··· 237 250 let val = this.config.extensions[ext.id]; 238 251 239 252 if (val == null) { 240 - this.config.extensions[ext.id] = { enabled }; 253 + this.config.extensions[ext.id] = enabled; 241 254 this.modified = this.isModified(); 242 255 this.emitChange(); 243 256 return; ··· 254 267 this.emitChange(); 255 268 } 256 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 + 257 287 async installExtension(uniqueId: number) { 258 288 const ext = this.getExtension(uniqueId); 259 289 if (!("download" in ext.manifest)) { ··· 274 304 existing.settingsOverride = update.updateManifest.settings; 275 305 existing.compat = checkExtensionCompat(update.updateManifest); 276 306 existing.manifest = update.updateManifest; 277 - existing.hasUpdate = false; 278 307 existing.changelog = update.updateManifest.meta?.changelog; 279 308 } 280 309 ··· 346 375 } 347 376 348 377 async updateMoonlight() { 349 - await natives.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(); 350 390 } 351 391 352 392 getConfigOption<K extends keyof Config>(key: K): Config[K] { ··· 374 414 } 375 415 376 416 #computeRestartAdvice() { 417 + // If moonlight update needs a restart, always hide advice. 418 + if (this.#updateState === UpdateState.Installed) return RestartAdvice.NotNeeded; 419 + 377 420 const i = this.initialConfig; // Initial config, from startup 378 421 const n = this.config; // New config about to be saved 379 422 ··· 403 446 // If it's enabled but not detected yet, restart. 404 447 if (newEnabled && !detected) { 405 448 return updateAdvice(RestartAdvice.RestartNeeded); 406 - continue; 407 449 } 408 450 409 451 // Toggling extensions specifically wants to rely on the initial state, 410 452 // that's what was considered when loading extensions. 411 453 const initEnabled = initState && (typeof initState === "boolean" ? initState : initState.enabled); 412 - if (initEnabled !== newEnabled) { 454 + if (initEnabled !== newEnabled || detected?.manifest.version !== ext.manifest.version) { 413 455 // If we have the extension locally, we confidently know if it has host/preload scripts. 414 456 // If not, we have to respect the environment specified in the manifest. 415 457 // If that is the default, we can't know what's needed. ··· 431 473 } 432 474 } 433 475 434 - const initConfig = typeof initState === "boolean" ? {} : initState.config ?? {}; 435 - const newConfig = typeof newState === "boolean" ? {} : newState.config ?? {}; 476 + const initConfig = typeof initState === "boolean" ? {} : { ...initState?.config }; 477 + const newConfig = typeof newState === "boolean" ? {} : { ...newState?.config }; 436 478 437 479 const def = ext.manifest.settings; 438 480 if (!def) continue; 439 481 482 + for (const key in def) { 483 + const defaultValue = def[key].default; 484 + 485 + initConfig[key] ??= defaultValue; 486 + newConfig[key] ??= defaultValue; 487 + } 488 + 440 489 const changedKeys = diff(initConfig, newConfig, { cyclesFix: false }).map((c) => c.path[0]); 441 490 for (const key in def) { 442 491 if (!changedKeys.includes(key)) continue; ··· 461 510 return returnedAdvice; 462 511 } 463 512 464 - writeConfig() { 465 - this.submitting = true; 466 - this.restartAdvice = this.#computeRestartAdvice(); 513 + async writeConfig() { 514 + try { 515 + this.submitting = true; 516 + this.emitChange(); 467 517 468 - moonlightNode.writeConfig(this.config); 469 - this.savedConfig = this.clone(this.config); 518 + await moonlightNode.writeConfig(this.config); 519 + await this.processConfigChanged(); 520 + } finally { 521 + this.submitting = false; 522 + this.emitChange(); 523 + } 524 + } 470 525 471 - this.submitting = false; 526 + private async processConfigChanged() { 527 + this.savedConfig = this.clone(this.config); 528 + this.restartAdvice = this.#computeRestartAdvice(); 472 529 this.modified = false; 530 + 531 + const modifiedRepos = diff(this.savedConfig.repositories, this.config.repositories); 532 + if (modifiedRepos.length !== 0) await this.checkUpdates(); 533 + 473 534 this.emitChange(); 474 535 } 475 536
+2 -4
packages/core-extensions/src/moonbase/webpackModules/ui/HelpMessage.tsx
··· 1 1 import React from "@moonlight-mod/wp/react"; 2 - import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 3 2 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 4 3 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.findByExports("positive", "iconDiv")[0].exports; 4 + import HelpMessageClasses from "@moonlight-mod/wp/discord/components/common/HelpMessage.css"; 5 + import Margins from "@moonlight-mod/wp/discord/styles/shared/Margins.css"; 8 6 9 7 // reimpl of HelpMessage but with a custom icon 10 8 export default function HelpMessage({
+1 -5
packages/core-extensions/src/moonbase/webpackModules/ui/RestartAdvice.tsx
··· 1 1 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 2 2 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 3 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 3 + import { Button, CircleWarningIcon } from "@moonlight-mod/wp/discord/components/common/index"; 4 4 import React from "@moonlight-mod/wp/react"; 5 5 import { RestartAdvice } from "../../types"; 6 6 import HelpMessage from "./HelpMessage"; 7 - 8 - const { Button } = Components; 9 7 10 8 const strings: Record<RestartAdvice, string> = { 11 9 [RestartAdvice.NotNeeded]: "how did you even", ··· 27 25 [RestartAdvice.ReloadNeeded]: () => window.location.reload(), 28 26 [RestartAdvice.RestartNeeded]: () => MoonbaseSettingsStore.restartDiscord() 29 27 }; 30 - 31 - const { CircleWarningIcon } = Components; 32 28 33 29 export default function RestartAdviceMessage() { 34 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 16 Clickable 17 17 } from "@moonlight-mod/wp/discord/components/common/index"; 18 18 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 19 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 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"; 20 22 21 23 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 22 24 23 - const FormClasses = spacepack.findByCode("dividerDefault:")[0].exports; 24 - const Margins = spacepack.findByCode("marginCenterHorz:")[0].exports; 25 - 26 - let RemoveButtonClasses: any; 25 + let GuildSettingsRoleEditClasses: any; 27 26 spacepack 28 27 .lazyLoad( 29 28 "renderArtisanalHack", 30 29 /\[(?:.\.e\("\d+?"\),?)+\][^}]+?webpackId:\d+,name:"GuildSettings"/, 31 30 /webpackId:(\d+),name:"GuildSettings"/ 32 31 ) 33 - .then(() => (RemoveButtonClasses = spacepack.findByCode("removeButtonContainer")[0].exports)); 34 - 35 - // FIXME: type component keys 36 - const { CircleXIcon } = Components; 32 + .then( 33 + () => 34 + (GuildSettingsRoleEditClasses = spacepack.require( 35 + "discord/modules/guild_settings/roles/web/GuildSettingsRoleEdit.css" 36 + )) 37 + ); 37 38 38 39 function RemoveEntryButton({ onClick }: { onClick: () => void }) { 39 40 return ( 40 - <div className={RemoveButtonClasses.removeButtonContainer}> 41 + <div className={GuildSettingsRoleEditClasses.removeButtonContainer}> 41 42 <Tooltip text="Remove entry" position="top"> 42 43 {(props: any) => ( 43 - <Clickable {...props} className={RemoveButtonClasses.removeButton} onClick={onClick}> 44 + <Clickable {...props} className={GuildSettingsRoleEditClasses.removeButton} onClick={onClick}> 44 45 <CircleXIcon width={24} height={24} /> 45 46 </Clickable> 46 47 )} ··· 121 122 <FormText className={Margins.marginBottom4}>A list of remote repositories to display extensions from</FormText> 122 123 <ArrayFormItem config="repositories" /> 123 124 </FormItem> 124 - <FormDivider className={FormClasses.dividerDefault} /> 125 + <FormDivider className={FormSwitchClasses.dividerDefault} /> 125 126 <FormItem title="Extension search paths" className={Margins.marginTop20}> 126 127 <FormText className={Margins.marginBottom4}> 127 128 A list of local directories to search for built extensions 128 129 </FormText> 129 130 <ArrayFormItem config="devSearchPaths" /> 130 131 </FormItem> 131 - <FormDivider className={FormClasses.dividerDefault} /> 132 + <FormDivider className={FormSwitchClasses.dividerDefault} /> 132 133 <FormSwitch 133 134 className={Margins.marginTop20} 134 135 value={MoonbaseSettingsStore.getConfigOption("patchAll") ?? false}
+138 -75
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/card.tsx
··· 1 1 import { ExtensionState } from "../../../types"; 2 2 import { constants, ExtensionLoadSource, ExtensionTag } from "@moonlight-mod/types"; 3 + 3 4 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"; 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"; 7 21 import React from "@moonlight-mod/wp/react"; 8 22 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 9 23 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 10 24 import MarkupUtils from "@moonlight-mod/wp/discord/modules/markup/MarkupUtils"; 11 - import IntegrationCard from "@moonlight-mod/wp/discord/modules/guild_settings/IntegrationCard.css"; 12 - 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"; 13 32 import ExtensionInfo from "./info"; 14 33 import Settings from "./settings"; 15 34 import { doGenericExtensionPopup, doMissingExtensionPopup } from "./popup"; ··· 21 40 Settings 22 41 } 23 42 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.findByExports("tabBar", "tabBarItem", "headerContentWrapper")[0].exports; 30 - const MarkupClasses = spacepack.findByExports("markup", "inlineFormat")[0].exports; 31 - 32 - const BuildOverrideClasses = spacepack.findByExports("disabledButtonOverride")[0].exports; 33 - 34 43 const COMPAT_TEXT_MAP: Record<ExtensionCompat, string> = { 35 44 [ExtensionCompat.Compatible]: "huh?", 36 45 [ExtensionCompat.InvalidApiLevel]: "Incompatible API level", ··· 38 47 }; 39 48 const CONFLICTING_TEXT = "This extension is already installed from another source."; 40 49 41 - export default function ExtensionCard({ uniqueId }: { uniqueId: number }) { 42 - const [tab, setTab] = React.useState(ExtensionPage.Info); 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 + } 43 61 62 + export default function ExtensionCard({ uniqueId, selectTag }: { uniqueId: number; selectTag: (tag: string) => void }) { 44 63 const { ext, enabled, busy, update, conflicting } = useStateFromStores([MoonbaseSettingsStore], () => { 45 64 return { 46 65 ext: MoonbaseSettingsStore.getExtension(uniqueId), ··· 51 70 }; 52 71 }); 53 72 54 - // Why it work like that :sob: 55 - if (ext == null) return <></>; 56 - 57 - const { Card, Text, FormSwitch, TabBar, Button } = Components; 73 + const [tab, setTab] = React.useState( 74 + update != null && ext?.changelog != null ? ExtensionPage.Changelog : ExtensionPage.Info 75 + ); 58 76 59 77 const tagline = ext.manifest?.meta?.tagline; 60 78 const settings = ext.settingsOverride ?? ext.manifest?.settings; 61 79 const description = ext.manifest?.meta?.description; 62 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 + 63 91 const enabledDependants = useStateFromStores([MoonbaseSettingsStore], () => 64 92 Object.keys(MoonbaseSettingsStore.extensions) 65 93 .filter((uniqueId) => { 66 94 const potentialDependant = MoonbaseSettingsStore.getExtension(parseInt(uniqueId)); 67 95 68 96 return ( 69 - potentialDependant.manifest.dependencies?.includes(ext.id) && 97 + potentialDependant.manifest.dependencies?.includes(ext?.id) && 70 98 MoonbaseSettingsStore.getExtensionEnabled(parseInt(uniqueId)) 71 99 ); 72 100 }) ··· 74 102 ); 75 103 const implicitlyEnabled = enabledDependants.length > 0; 76 104 77 - return ( 78 - <Card editable={true} className={IntegrationCard.card}> 79 - <div className={IntegrationCard.cardHeader}> 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}> 80 117 <Flex direction={Flex.Direction.VERTICAL}> 81 118 <Flex direction={Flex.Direction.HORIZONTAL} align={Flex.Align.CENTER}> 82 119 <Text variant="text-md/semibold">{ext.manifest?.meta?.name ?? ext.id}</Text> 83 120 {ext.source.type === ExtensionLoadSource.Developer && ( 84 121 <Tooltip text="This is a local extension" position="top"> 85 - {(props: any) => <BeakerIcon {...props} class={BuildOverrideClasses.infoIcon} size="xs" />} 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" />} 86 135 </Tooltip> 87 136 )} 88 137 </Flex> ··· 99 148 gap: "1rem" 100 149 }} 101 150 > 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 151 {ext.state === ExtensionState.NotDownloaded ? ( 113 152 <Tooltip 114 153 text={conflicting ? CONFLICTING_TEXT : COMPAT_TEXT_MAP[ext.compat]} ··· 164 203 disabled={implicitlyEnabled || ext.compat !== ExtensionCompat.Compatible} 165 204 hideBorder={true} 166 205 style={{ marginBottom: "0px" }} 206 + // @ts-expect-error fix type later 167 207 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 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 175 220 } 176 221 onChange={() => { 177 222 const toggle = () => { ··· 204 249 </div> 205 250 206 251 <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 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 224 265 </TabBar.Item> 225 - )} 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 + )} 226 278 227 - {changelog != null && ( 228 - <TabBar.Item className={TabBarClasses.tabBarItem} id={ExtensionPage.Changelog}> 229 - Changelog 230 - </TabBar.Item> 231 - )} 279 + {settings != null && ( 280 + <TabBar.Item className={DiscoveryClasses.tabBarItem} id={ExtensionPage.Settings}> 281 + Settings 282 + </TabBar.Item> 283 + )} 284 + </TabBar> 232 285 233 - {settings != null && ( 234 - <TabBar.Item className={TabBarClasses.tabBarItem} id={ExtensionPage.Settings}> 235 - Settings 236 - </TabBar.Item> 237 - )} 238 - </TabBar> 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> 239 296 )} 240 297 241 298 <Flex 242 299 justify={Flex.Justify.START} 243 300 wrap={Flex.Wrap.WRAP} 244 301 style={{ 245 - padding: "16px 16px" 302 + padding: "16px 16px", 303 + // This looks wonky in the settings tab 304 + rowGap: tab === ExtensionPage.Info ? "16px" : undefined 246 305 }} 247 306 > 248 - {tab === ExtensionPage.Info && <ExtensionInfo ext={ext} />} 307 + {tab === ExtensionPage.Info && <ExtensionInfo ext={ext} selectTag={selectTag} />} 249 308 {tab === ExtensionPage.Description && ( 250 309 <Text variant="text-md/normal" className={MarkupClasses.markup} style={{ width: "100%" }}> 251 310 {MarkupUtils.parse(description ?? "*No description*", true, { ··· 264 323 })} 265 324 </Text> 266 325 )} 267 - {tab === ExtensionPage.Settings && <Settings ext={ext} />} 326 + {tab === ExtensionPage.Settings && ( 327 + <ErrorBoundary> 328 + <Settings ext={ext} /> 329 + </ErrorBoundary> 330 + )} 268 331 </Flex> 269 332 </div> 270 333 </Card>
+67 -52
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/filterBar.tsx
··· 1 1 import { tagNames } from "./info"; 2 - 3 2 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 4 3 import * as React from "@moonlight-mod/wp/react"; 5 4 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; ··· 11 10 Popout, 12 11 Dialog, 13 12 Menu, 14 - MenuGroup, 15 - MenuCheckboxItem, 16 - MenuItem 13 + ChevronSmallDownIcon, 14 + ChevronSmallUpIcon, 15 + ArrowsUpDownIcon, 16 + RetryIcon, 17 + Tooltip 17 18 } from "@moonlight-mod/wp/discord/components/common/index"; 18 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 19 + import { MenuGroup, MenuCheckboxItem, MenuItem } from "@moonlight-mod/wp/contextMenu_contextMenu"; 19 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"; 20 23 21 24 export enum Filter { 22 25 Core = 1 << 0, ··· 26 29 Disabled = 1 << 4, 27 30 Installed = 1 << 5, 28 31 Repository = 1 << 6, 29 - Incompatible = 1 << 7 32 + Incompatible = 1 << 7, 33 + Deprecated = 1 << 8 30 34 } 31 35 export const defaultFilter = 127 as Filter; 32 36 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; 37 + let HeaderClasses: any; 38 + let ForumsClasses: any; 39 + let SortMenuClasses: any; 38 40 spacepack 39 41 .lazyLoad('"Missing channel in Channel.openChannelContextMenu"', /e\("(\d+)"\)/g, /webpackId:(\d+?),/) 40 42 .then(() => { 41 - FilterBarClasses = spacepack.findByCode("tagsButtonWithCount:")[0].exports; 42 - FilterDialogClasses = spacepack.findByCode("countContainer:", "tagContainer:")[0].exports; 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"); 43 46 }); 44 47 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 48 function toggleTag(selectedTags: Set<string>, setSelectedTags: (tags: Set<string>) => void, tag: string) { 51 49 const newState = new Set(selectedTags); 52 50 if (newState.has(tag)) newState.delete(tag); ··· 123 121 checked={(filter & Filter.Incompatible) === Filter.Incompatible} 124 122 action={() => toggleFilter(Filter.Incompatible)} 125 123 /> 124 + <MenuCheckboxItem 125 + id="l-deprecated" 126 + label="Show deprecated" 127 + checked={(filter & Filter.Deprecated) === Filter.Deprecated} 128 + action={() => toggleFilter(Filter.Deprecated)} 129 + /> 126 130 <MenuItem 127 131 id="reset-all" 128 132 className={SortMenuClasses.clearText} ··· 140 144 141 145 function TagButtonPopout({ selectedTags, setSelectedTags, setPopoutRef, closePopout }: any) { 142 146 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 + <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}> 147 151 Select tags 148 152 </Heading> 149 - <div className={FilterDialogClasses.countContainer}> 150 - <Text className={FilterDialogClasses.countText} color="none" variant="text-xs/medium"> 153 + <div className={HeaderClasses.countContainer}> 154 + <Text className={HeaderClasses.countText} color="none" variant="text-xs/medium"> 151 155 {selectedTags.size} 152 156 </Text> 153 157 </div> 154 158 </div> 155 159 </div> 156 - <div className={FilterDialogClasses.tagContainer}> 160 + <div className={HeaderClasses.tagContainer}> 157 161 {Object.keys(tagNames).map((tag) => ( 158 162 <TagItem 159 163 key={tag} 160 - className={FilterDialogClasses.tag} 161 - tag={{ name: tagNames[tag as keyof typeof tagNames] }} 164 + className={HeaderClasses.tag} 165 + tag={{ name: tagNames[tag as keyof typeof tagNames], id: tagNames[tag as keyof typeof tagNames] }} 162 166 onClick={() => toggleTag(selectedTags, setSelectedTags, tag)} 163 167 selected={selectedTags.has(tag)} 164 168 /> 165 169 ))} 166 170 </div> 167 - <div className={FilterDialogClasses.separator} /> 171 + <div className={HeaderClasses.separator} /> 168 172 <Button 169 173 look={Button.Looks.LINK} 170 174 size={Button.Sizes.MIN} 171 175 color={Button.Colors.CUSTOM} 172 - className={FilterDialogClasses.clear} 176 + className={HeaderClasses.clear} 173 177 onClick={() => { 174 178 setSelectedTags(new Set()); 175 179 closePopout(); ··· 199 203 const tagsContainer = React.useRef<HTMLDivElement>(null); 200 204 const tagListInner = React.useRef<HTMLDivElement>(null); 201 205 const [tagsButtonOffset, setTagsButtonOffset] = React.useState(0); 206 + const [checkingUpdates, setCheckingUpdates] = React.useState(false); 207 + 202 208 React.useLayoutEffect(() => { 203 209 if (tagsContainer.current === null || tagListInner.current === null) return; 204 210 const { left: containerX, top: containerY } = tagsContainer.current.getBoundingClientRect(); ··· 220 226 style={{ 221 227 paddingTop: "12px" 222 228 }} 223 - className={`${FilterBarClasses.tagsContainer} ${Margins.marginBottom8}`} 229 + className={`${ForumsClasses.tagsContainer} ${Margins.marginBottom8}`} 224 230 > 225 231 <Tooltip text="Refresh updates" position="top"> 226 232 {(props: any) => ( ··· 228 234 {...props} 229 235 size={Button.Sizes.MIN} 230 236 color={Button.Colors.CUSTOM} 231 - className={`${FilterBarClasses.sortDropdown} moonbase-retry-button`} 232 - innerClassName={FilterBarClasses.sortDropdownInner} 233 - onClick={() => MoonbaseSettingsStore.checkUpdates()} 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 + }} 234 251 > 235 - <RetryIcon size={"custom"} width={16} /> 252 + <RetryIcon size={"custom"} width={16} className={checkingUpdates ? "moonbase-speen" : ""} /> 236 253 </Button> 237 254 )} 238 255 </Tooltip> ··· 248 265 {...props} 249 266 size={Button.Sizes.MIN} 250 267 color={Button.Colors.CUSTOM} 251 - className={FilterBarClasses.sortDropdown} 252 - innerClassName={FilterBarClasses.sortDropdownInner} 268 + className={ForumsClasses.sortDropdown} 269 + innerClassName={ForumsClasses.sortDropdownInner} 253 270 > 254 271 <ArrowsUpDownIcon size="xs" /> 255 - <Text className={FilterBarClasses.sortDropdownText} variant="text-sm/medium" color="interactive-normal"> 272 + <Text className={ForumsClasses.sortDropdownText} variant="text-sm/medium" color="interactive-normal"> 256 273 Sort & filter 257 274 </Text> 258 275 {isShown ? ( ··· 263 280 </Button> 264 281 )} 265 282 </Popout> 266 - <div className={FilterBarClasses.divider} /> 267 - <div className={FilterBarClasses.tagList}> 268 - <div ref={tagListInner} className={FilterBarClasses.tagListInner}> 283 + <div className={ForumsClasses.divider} /> 284 + <div className={ForumsClasses.tagList}> 285 + <div ref={tagListInner} className={ForumsClasses.tagListInner}> 269 286 {Object.keys(tagNames).map((tag) => ( 270 287 <TagItem 271 288 key={tag} 272 - className={FilterBarClasses.tag} 273 - tag={{ name: tagNames[tag as keyof typeof tagNames] }} 289 + className={ForumsClasses.tag} 290 + tag={{ name: tagNames[tag as keyof typeof tagNames], id: tag }} 274 291 onClick={() => toggleTag(selectedTags, setSelectedTags, tag)} 275 292 selected={selectedTags.has(tag)} 276 293 /> ··· 298 315 left: tagsButtonOffset 299 316 }} 300 317 // TODO: Use Discord's class name utility 301 - className={`${FilterBarClasses.tagsButton} ${ 302 - selectedTags.size > 0 ? FilterBarClasses.tagsButtonWithCount : "" 303 - }`} 304 - innerClassName={FilterBarClasses.tagsButtonInner} 318 + className={`${ForumsClasses.tagsButton} ${selectedTags.size > 0 ? ForumsClasses.tagsButtonWithCount : ""}`} 319 + innerClassName={ForumsClasses.tagsButtonInner} 305 320 > 306 321 {selectedTags.size > 0 ? ( 307 - <div style={{ boxSizing: "content-box" }} className={FilterBarClasses.countContainer}> 308 - <Text className={FilterBarClasses.countText} color="none" variant="text-xs/medium"> 322 + <div style={{ boxSizing: "content-box" }} className={ForumsClasses.countContainer}> 323 + <Text className={ForumsClasses.countText} color="none" variant="text-xs/medium"> 309 324 {selectedTags.size} 310 325 </Text> 311 326 </div> ··· 323 338 <Button 324 339 size={Button.Sizes.MIN} 325 340 color={Button.Colors.CUSTOM} 326 - className={`${FilterBarClasses.tagsButton} ${FilterBarClasses.tagsButtonPlaceholder}`} 327 - innerClassName={FilterBarClasses.tagsButtonInner} 341 + className={`${ForumsClasses.tagsButton} ${ForumsClasses.tagsButtonPlaceholder}`} 342 + innerClassName={ForumsClasses.tagsButtonInner} 328 343 > 329 344 {selectedTags.size > 0 ? ( 330 - <div style={{ boxSizing: "content-box" }} className={FilterBarClasses.countContainer}> 331 - <Text className={FilterBarClasses.countText} color="none" variant="text-xs/medium"> 345 + <div style={{ boxSizing: "content-box" }} className={ForumsClasses.countContainer}> 346 + <Text className={ForumsClasses.countText} color="none" variant="text-xs/medium"> 332 347 {selectedTags.size} 333 348 </Text> 334 349 </div>
+49 -15
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/index.tsx
··· 6 6 import React from "@moonlight-mod/wp/react"; 7 7 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 8 8 import { useStateFromStoresObject } from "@moonlight-mod/wp/discord/packages/flux"; 9 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 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"; 10 16 11 17 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 18 + import ErrorBoundary from "@moonlight-mod/wp/common_ErrorBoundary"; 12 19 import { ExtensionCompat } from "@moonlight-mod/core/extension/loader"; 13 20 import HelpMessage from "../HelpMessage"; 14 21 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; 22 + const SearchBar = spacepack.require("discord/uikit/search/SearchBar").default; 23 + 24 + const validTags: string[] = Object.values(ExtensionTag); 18 25 19 26 export default function ExtensionsPage() { 20 - const { extensions, savedFilter, showOnlyUpdateable } = useStateFromStoresObject([MoonbaseSettingsStore], () => { 27 + const { extensions, savedFilter } = useStateFromStoresObject([MoonbaseSettingsStore], () => { 21 28 return { 22 29 extensions: MoonbaseSettingsStore.extensions, 23 - savedFilter: MoonbaseSettingsStore.getExtensionConfigRaw<number>("moonbase", "filter", defaultFilter), 24 - showOnlyUpdateable: MoonbaseSettingsStore.showOnlyUpdateable 30 + savedFilter: MoonbaseSettingsStore.getExtensionConfigRaw<number>("moonbase", "filter", defaultFilter) 25 31 }; 26 32 }); 27 33 28 34 const [query, setQuery] = React.useState(""); 35 + const [hitUpdateAll, setHitUpdateAll] = React.useState(false); 29 36 30 37 const filterState = React.useState(defaultFilter); 31 38 ··· 37 44 filter = filterState[0]; 38 45 setFilter = filterState[1]; 39 46 } 47 + 40 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 + 41 58 const sorted = Object.values(extensions).sort((a, b) => { 42 59 const aName = a.manifest.meta?.name ?? a.id; 43 60 const bName = b.manifest.meta?.name ?? b.id; ··· 72 89 ) && 73 90 (filter & Filter.Incompatible || 74 91 ext.compat === ExtensionCompat.Compatible || 75 - (ext.compat === ExtensionCompat.InvalidApiLevel && ext.hasUpdate)) 92 + (ext.compat === ExtensionCompat.InvalidApiLevel && ext.hasUpdate)) && 93 + (filter & Filter.Deprecated || 94 + ext.manifest?.meta?.deprecated !== true || 95 + ext.state !== ExtensionState.NotDownloaded) 76 96 ); 77 97 78 98 // Prioritize extensions with updates 79 99 const filteredWithUpdates = filtered.filter((ext) => ext!.hasUpdate); 80 - const filterUpdates = showOnlyUpdateable && filteredWithUpdates.length > 0; 81 - const filteredWithoutUpdates = filterUpdates ? [] : filtered.filter((ext) => !ext!.hasUpdate); 100 + const filteredWithoutUpdates = filtered.filter((ext) => !ext!.hasUpdate); 82 101 83 102 return ( 84 103 <> ··· 97 116 /> 98 117 <FilterBar filter={filter} setFilter={setFilter} selectedTags={selectedTags} setSelectedTags={setSelectedTags} /> 99 118 100 - {filterUpdates && ( 119 + {filteredWithUpdates.length > 0 && ( 101 120 <HelpMessage 102 121 icon={CircleInformationIcon} 103 - text="Only displaying updates" 122 + text="Extension updates are available" 104 123 className="moonbase-extension-update-section" 105 124 > 106 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> 107 137 <PanelButton 108 138 icon={XSmallIcon} 109 139 onClick={() => { 110 - MoonbaseSettingsStore.showOnlyUpdateable = false; 140 + MoonbaseSettingsStore.dismissAllExtensionUpdates(); 111 141 }} 112 142 /> 113 143 </div> ··· 115 145 )} 116 146 117 147 {filteredWithUpdates.map((ext) => ( 118 - <ExtensionCard uniqueId={ext.uniqueId} key={ext.uniqueId} /> 148 + <ErrorBoundary> 149 + <ExtensionCard uniqueId={ext.uniqueId} key={ext.uniqueId} selectTag={selectTag} /> 150 + </ErrorBoundary> 119 151 ))} 120 152 {filteredWithUpdates.length > 0 && filteredWithoutUpdates.length > 0 && ( 121 153 <FormDivider className="moonbase-update-divider" /> 122 154 )} 123 155 {filteredWithoutUpdates.map((ext) => ( 124 - <ExtensionCard uniqueId={ext.uniqueId} key={ext.uniqueId} /> 156 + <ErrorBoundary> 157 + <ExtensionCard uniqueId={ext.uniqueId} key={ext.uniqueId} selectTag={selectTag} /> 158 + </ErrorBoundary> 125 159 ))} 126 160 </> 127 161 );
+55 -26
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/info.tsx
··· 2 2 import { MoonbaseExtension } from "../../../types"; 3 3 4 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"; 5 + import { Text } from "@moonlight-mod/wp/discord/components/common/index"; 7 6 8 7 type Dependency = { 9 8 id: string; ··· 34 33 [ExtensionTag.Library]: "Library" 35 34 }; 36 35 37 - const UserInfoClasses = spacepack.findByCode("infoScroller", "userInfoSection", "userInfoSectionHeader")[0].exports; 38 - 39 36 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 40 - 41 - // FIXME: type component keys 42 - const { Text } = Components; 43 37 44 38 function InfoSection({ title, children }: { title: string; children: React.ReactNode }) { 45 39 return ( ··· 48 42 marginRight: "1em" 49 43 }} 50 44 > 51 - <Text variant="eyebrow" className={UserInfoClasses.userInfoSectionHeader}> 45 + <Text variant="eyebrow" className="moonlight-card-info-header"> 52 46 {title} 53 47 </Text> 54 48 ··· 57 51 ); 58 52 } 59 53 60 - function Badge({ color, children }: { color: string; children: React.ReactNode }) { 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"; 61 66 return ( 62 67 <span 63 - style={{ 64 - borderRadius: ".1875rem", 65 - padding: "0 0.275rem", 66 - marginRight: "0.4em", 67 - backgroundColor: color, 68 - color: "#fff" 69 - }} 68 + className="moonlight-card-badge" 69 + style={ 70 + { 71 + "--badge-color": color, 72 + ...style 73 + } as React.CSSProperties 74 + } 75 + onClick={onClick} 70 76 > 71 77 {children} 72 78 </span> 73 79 ); 74 80 } 75 81 76 - export default function ExtensionInfo({ ext }: { ext: MoonbaseExtension }) { 82 + export default function ExtensionInfo({ 83 + ext, 84 + selectTag 85 + }: { 86 + ext: MoonbaseExtension; 87 + selectTag: (tag: string) => void; 88 + }) { 77 89 const authors = ext.manifest?.meta?.authors; 78 90 const tags = ext.manifest?.meta?.tags; 79 91 const version = ext.manifest?.version; 80 92 81 93 const dependencies: Dependency[] = []; 94 + const incompatible: Dependency[] = []; 95 + 82 96 if (ext.manifest.dependencies != null) { 83 97 dependencies.push( 84 98 ...ext.manifest.dependencies.map((dep) => ({ ··· 98 112 } 99 113 100 114 if (ext.manifest.incompatible != null) { 101 - dependencies.push( 115 + incompatible.push( 102 116 ...ext.manifest.incompatible.map((dep) => ({ 103 117 id: dep, 104 118 type: DependencyType.Incompatible ··· 136 150 <InfoSection title="Tags"> 137 151 {tags.map((tag, i) => { 138 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 + } 139 159 140 160 return ( 141 - <Badge key={i} color={tag === ExtensionTag.DangerZone ? "var(--red-400)" : "var(--brand-500)"}> 161 + <Badge key={i} color={color} style={style} onClick={() => selectTag(tag)}> 142 162 {name} 143 163 </Badge> 144 164 ); ··· 149 169 {dependencies.length > 0 && ( 150 170 <InfoSection title="Dependencies"> 151 171 {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 172 const name = MoonbaseSettingsStore.tryGetExtensionName(dep.id); 159 173 174 + // TODO: figure out a decent way to distinguish suggested 160 175 return ( 161 - <Badge color={color} key={dep.id}> 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}> 162 191 {name} 163 192 </Badge> 164 193 );
+15 -11
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/popup.tsx
··· 1 1 // TODO: clean up the styling here 2 - import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 3 2 import React from "@moonlight-mod/wp/react"; 4 3 import { MoonbaseExtension } from "core-extensions/src/moonbase/types"; 5 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 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 6 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 7 7 import { ExtensionLoadSource } from "@moonlight-mod/types"; 8 8 import Flex from "@moonlight-mod/wp/discord/uikit/Flex"; 9 + import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 9 10 10 - const { openModalLazy, useModalsStore, closeModal } = Components; 11 - const Popup = spacepack.findByCode(".minorContainer", "secondaryAction")[0].exports.default; 11 + let ConfirmModal: typeof import("@moonlight-mod/wp/discord/components/modals/ConfirmModal").default; 12 12 13 13 function close() { 14 14 const ModalStore = useModalsStore.getState(); 15 15 closeModal(ModalStore.default[0].key); 16 16 } 17 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 + 18 25 const presentableLoadSources: Record<ExtensionLoadSource, string> = { 19 26 [ExtensionLoadSource.Developer]: "Local extension", // should never show up 20 27 [ExtensionLoadSource.Core]: "Core extension", ··· 32 39 option: string | undefined; 33 40 setOption: (pick: string | undefined) => void; 34 41 }) { 35 - const { SingleSelect } = Components; 36 - 37 42 return ( 38 43 <SingleSelect 39 44 key={id} ··· 61 66 deps: Record<string, MoonbaseExtension[]>; 62 67 transitionState: number | null; 63 68 }) { 64 - const { Text } = Components; 65 - 69 + lazyLoad(); 66 70 const amountNotAvailable = Object.values(deps).filter((candidates) => candidates.length === 0).length; 67 71 68 72 const [options, setOptions] = React.useState<Record<string, string | undefined>>( ··· 75 79 ); 76 80 77 81 return ( 78 - <Popup 82 + <ConfirmModal 79 83 body={ 80 84 <Flex 81 85 style={{ ··· 168 172 uniqueId: number; 169 173 cb: () => void; 170 174 }) { 171 - const { Text } = Components; 175 + lazyLoad(); 172 176 173 177 return ( 174 - <Popup 178 + <ConfirmModal 175 179 title={title} 176 180 body={ 177 181 <Flex>
+84 -50
packages/core-extensions/src/moonbase/webpackModules/ui/extensions/settings.tsx
··· 11 11 12 12 import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 13 13 import React from "@moonlight-mod/wp/react"; 14 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 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"; 15 32 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 16 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 + ); 17 51 18 52 type SettingsProps = { 19 53 ext: MoonbaseExtension; ··· 21 55 setting: ExtensionSettingsManifest; 22 56 disabled: boolean; 23 57 }; 24 - 25 58 type SettingsComponent = React.ComponentType<SettingsProps>; 26 59 27 - import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 28 60 const Margins = spacepack.require("discord/styles/shared/Margins.css"); 29 61 62 + function markdownify(str: string) { 63 + return MarkupUtils.parse(str, true, { 64 + hideSimpleEmbedContent: true, 65 + allowLinks: true 66 + }); 67 + } 68 + 30 69 function useConfigEntry<T>(uniqueId: number, name: string) { 31 70 return useStateFromStores( 32 71 [MoonbaseSettingsStore], ··· 42 81 } 43 82 44 83 function Boolean({ ext, name, setting, disabled }: SettingsProps) { 45 - const { FormSwitch } = Components; 46 84 const { value, displayName, description } = useConfigEntry<boolean>(ext.uniqueId, name); 47 85 48 86 return ( ··· 53 91 onChange={(value: boolean) => { 54 92 MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value); 55 93 }} 56 - note={description} 94 + note={description != null ? markdownify(description) : undefined} 57 95 className={`${Margins.marginReset} ${Margins.marginTop20}`} 58 96 > 59 97 {displayName} ··· 62 100 } 63 101 64 102 function Number({ ext, name, setting, disabled }: SettingsProps) { 65 - const { FormItem, FormText, Slider } = Components; 66 103 const { value, displayName, description } = useConfigEntry<number>(ext.uniqueId, name); 67 104 68 105 const castedSetting = setting as NumberSettingType; 69 - const min = castedSetting.min ?? 0; 70 - const max = castedSetting.max ?? 100; 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 + }; 71 113 72 114 return ( 73 115 <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 - /> 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 + )} 85 134 </FormItem> 86 135 ); 87 136 } 88 137 89 138 function String({ ext, name, setting, disabled }: SettingsProps) { 90 - const { FormItem, FormText, TextInput } = Components; 91 139 const { value, displayName, description } = useConfigEntry<string>(ext.uniqueId, name); 92 140 93 141 return ( 94 142 <FormItem className={Margins.marginTop20} title={displayName}> 95 - {description && <FormText className={Margins.marginBottom8}>{description}</FormText>} 143 + {description && <FormText className={Margins.marginBottom8}>{markdownify(description)}</FormText>} 96 144 <TextInput 97 145 value={value ?? ""} 98 - onChange={(value: string) => { 99 - if (disabled) return; 100 - MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value); 101 - }} 146 + disabled={disabled} 147 + onChange={(value: string) => MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value)} 102 148 /> 103 149 </FormItem> 104 150 ); 105 151 } 106 152 107 153 function MultilineString({ ext, name, setting, disabled }: SettingsProps) { 108 - const { FormItem, FormText, TextArea } = Components; 109 154 const { value, displayName, description } = useConfigEntry<string>(ext.uniqueId, name); 110 155 111 156 return ( 112 157 <FormItem className={Margins.marginTop20} title={displayName}> 113 - {description && <FormText className={Margins.marginBottom8}>{description}</FormText>} 158 + {description && <FormText className={Margins.marginBottom8}>{markdownify(description)}</FormText>} 114 159 <TextArea 115 160 rows={5} 116 161 value={value ?? ""} 162 + disabled={disabled} 117 163 className={"moonbase-resizeable"} 118 - onChange={(value: string) => { 119 - if (disabled) return; 120 - MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value); 121 - }} 164 + onChange={(value: string) => MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value)} 122 165 /> 123 166 </FormItem> 124 167 ); 125 168 } 126 169 127 170 function Select({ ext, name, setting, disabled }: SettingsProps) { 128 - const { FormItem, FormText, SingleSelect } = Components; 129 171 const { value, displayName, description } = useConfigEntry<string>(ext.uniqueId, name); 130 172 131 173 const castedSetting = setting as SelectSettingType; ··· 133 175 134 176 return ( 135 177 <FormItem className={Margins.marginTop20} title={displayName}> 136 - {description && <FormText className={Margins.marginBottom8}>{description}</FormText>} 178 + {description && <FormText className={Margins.marginBottom8}>{markdownify(description)}</FormText>} 137 179 <SingleSelect 138 180 autofocus={false} 139 181 clearable={false} ··· 149 191 } 150 192 151 193 function MultiSelect({ ext, name, setting, disabled }: SettingsProps) { 152 - const { FormItem, FormText, Select, useVariableSelect, multiSelect } = Components; 153 194 const { value, displayName, description } = useConfigEntry<string | string[]>(ext.uniqueId, name); 154 195 155 196 const castedSetting = setting as MultiSelectSettingType; ··· 157 198 158 199 return ( 159 200 <FormItem className={Margins.marginTop20} title={displayName}> 160 - {description && <FormText className={Margins.marginBottom8}>{description}</FormText>} 161 - <Select 201 + {description && <FormText className={Margins.marginBottom8}>{markdownify(description)}</FormText>} 202 + <DiscordSelect 162 203 autofocus={false} 163 204 clearable={false} 164 205 closeOnSelect={false} ··· 175 216 </FormItem> 176 217 ); 177 218 } 178 - 179 - const RemoveButtonClasses = spacepack.findByCode("removeButtonContainer")[0].exports; 180 - 181 - // FIXME: type component keys 182 - const { CircleXIcon } = Components; 183 219 184 220 function RemoveEntryButton({ onClick, disabled }: { onClick: () => void; disabled: boolean }) { 185 - const { Tooltip, Clickable } = Components; 186 221 return ( 187 - <div className={RemoveButtonClasses.removeButtonContainer}> 222 + <div className={GuildSettingsRoleEditClasses.removeButtonContainer}> 188 223 <Tooltip text="Remove entry" position="top"> 189 224 {(props: any) => ( 190 - <Clickable {...props} className={RemoveButtonClasses.removeButton} onClick={onClick}> 225 + <Clickable {...props} className={GuildSettingsRoleEditClasses.removeButton} onClick={onClick}> 191 226 <CircleXIcon width={16} height={16} /> 192 227 </Clickable> 193 228 )} ··· 197 232 } 198 233 199 234 function List({ ext, name, setting, disabled }: SettingsProps) { 200 - const { FormItem, FormText, TextInput, Button } = Components; 201 235 const { value, displayName, description } = useConfigEntry<string[]>(ext.uniqueId, name); 202 236 203 237 const entries = value ?? []; ··· 205 239 206 240 return ( 207 241 <FormItem className={Margins.marginTop20} title={displayName}> 208 - {description && <FormText className={Margins.marginBottom4}>{description}</FormText>} 242 + {description && <FormText className={Margins.marginBottom4}>{markdownify(description)}</FormText>} 209 243 <Flex direction={Flex.Direction.VERTICAL}> 210 244 {entries.map((val, i) => ( 211 245 // FIXME: stylesheets ··· 257 291 } 258 292 259 293 function Dictionary({ ext, name, setting, disabled }: SettingsProps) { 260 - const { FormItem, FormText, TextInput, Button } = Components; 261 294 const { value, displayName, description } = useConfigEntry<Record<string, string>>(ext.uniqueId, name); 262 295 263 296 const entries = Object.entries(value ?? {}); ··· 265 298 266 299 return ( 267 300 <FormItem className={Margins.marginTop20} title={displayName}> 268 - {description && <FormText className={Margins.marginBottom4}>{description}</FormText>} 301 + {description && <FormText className={Margins.marginBottom4}>{markdownify(description)}</FormText>} 269 302 <Flex direction={Flex.Direction.VERTICAL}> 270 303 {entries.map(([key, val], i) => ( 271 304 // FIXME: stylesheets ··· 339 372 ); 340 373 341 374 if (Component == null) { 342 - const { Text } = Components; 343 375 return ( 344 376 <Text variant="text-md/normal">{`Custom setting "${displayName}" is missing a component. Perhaps the extension is not installed?`}</Text> 345 377 ); 346 378 } 347 379 348 380 return ( 349 - <Component value={value} setValue={(value) => MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value)} /> 381 + <ErrorBoundary> 382 + <Component value={value} setValue={(value) => MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value)} /> 383 + </ErrorBoundary> 350 384 ); 351 385 } 352 386
+22 -15
packages/core-extensions/src/moonbase/webpackModules/ui/index.tsx
··· 1 1 import React from "@moonlight-mod/wp/react"; 2 - import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 3 2 import { Text, TabBar } from "@moonlight-mod/wp/discord/components/common/index"; 4 3 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 5 4 import { UserSettingsModalStore } from "@moonlight-mod/wp/common_stores"; 6 5 7 6 import ExtensionsPage from "./extensions"; 8 7 import ConfigPage from "./config"; 8 + import AboutPage from "./about"; 9 9 import Update from "./update"; 10 - import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 11 10 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.findByExports("setSection", "clearSubsection")[0].exports.Z; 17 - const Margins = spacepack.require("discord/styles/shared/Margins.css"); 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"; 18 16 19 17 export const pages: { 20 18 id: string; ··· 30 28 id: "config", 31 29 name: "Config", 32 30 element: ConfigPage 31 + }, 32 + { 33 + id: "about", 34 + name: "About", 35 + element: AboutPage 33 36 } 34 37 ]; 35 38 ··· 37 40 const subsection = useStateFromStores([UserSettingsModalStore], () => UserSettingsModalStore.getSubsection() ?? 0); 38 41 const setSubsection = React.useCallback( 39 42 (to: string) => { 40 - if (subsection !== to) setSection("moonbase", to); 43 + if (subsection !== to) UserSettingsModalActionCreators.setSection("moonbase", to); 41 44 }, 42 45 [subsection] 43 46 ); ··· 45 48 React.useEffect( 46 49 () => () => { 47 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 48 - clearSubsection("moonbase"); 49 - MoonbaseSettingsStore.showOnlyUpdateable = false; 51 + UserSettingsModalActionCreators.clearSubsection("moonbase"); 50 52 }, 51 53 [] 52 54 ); 53 55 54 56 return ( 55 57 <> 56 - <div className={`${TitleBarClasses.children} ${Margins.marginBottom20}`}> 57 - <Text className={TitleBarClasses.titleWrapper} variant="heading-lg/semibold" tag="h2"> 58 + <div className={`${HeaderBarClasses.children} ${Margins.marginBottom20}`}> 59 + <Text className={HeaderBarClasses.titleWrapper} variant="heading-lg/semibold" tag="h2"> 58 60 Moonbase 59 61 </Text> 60 62 <Divider /> 61 - <TabBar selectedItem={subsection} onItemSelect={setSubsection} type="top-pill" className={TabBarClasses.tabBar}> 63 + <TabBar 64 + selectedItem={subsection} 65 + onItemSelect={setSubsection} 66 + type="top-pill" 67 + className={PeoplePageClasses.tabBar} 68 + > 62 69 {pages.map((page, i) => ( 63 - <TabBar.Item key={page.id} id={i} className={TabBarClasses.item}> 70 + <TabBar.Item key={page.id} id={i} className={PeoplePageClasses.item}> 64 71 {page.name} 65 72 </TabBar.Item> 66 73 ))}
+77 -15
packages/core-extensions/src/moonbase/webpackModules/ui/update.tsx
··· 1 1 import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux"; 2 2 import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores"; 3 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 4 3 import React from "@moonlight-mod/wp/react"; 5 4 import { UpdateState } from "../../types"; 6 5 import HelpMessage from "./HelpMessage"; 7 - 8 - const { ThemeDarkIcon, Button } = Components; 9 - 10 - const logger = moonlight.getLogger("moonbase/ui/update"); 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"; 11 22 12 23 const strings: Record<UpdateState, string> = { 13 24 [UpdateState.Ready]: "A new version of moonlight is available.", ··· 16 27 [UpdateState.Failed]: "Failed to update moonlight. Please use the installer instead." 17 28 }; 18 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 + 19 67 export default function Update() { 20 - const [state, setState] = React.useState(UpdateState.Ready); 21 - const newVersion = useStateFromStores([MoonbaseSettingsStore], () => MoonbaseSettingsStore.newVersion); 68 + const [newVersion, state] = useStateFromStores([MoonbaseSettingsStore], () => [ 69 + MoonbaseSettingsStore.newVersion, 70 + MoonbaseSettingsStore.updateState 71 + ]); 22 72 23 73 if (newVersion == null) return null; 24 74 25 75 return ( 26 76 <HelpMessage text={strings[state]} className="moonbase-update-section" icon={ThemeDarkIcon}> 27 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 + 28 97 {state === UpdateState.Installed && ( 29 98 <Button 30 99 look={Button.Looks.OUTLINED} ··· 44 113 size={Button.Sizes.TINY} 45 114 disabled={state !== UpdateState.Ready} 46 115 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 - }); 116 + MoonbaseSettingsStore.updateMoonlight(); 55 117 }} 56 118 > 57 119 Update
+3 -6
packages/core-extensions/src/moonbase/webpackModules/updates.tsx
··· 3 3 import Notices from "@moonlight-mod/wp/notices_notices"; 4 4 import { MoonlightBranch } from "@moonlight-mod/types"; 5 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; 6 + import ThemeDarkIcon from "@moonlight-mod/wp/moonbase_ThemeDarkIcon"; 9 7 10 8 function plural(str: string, num: number) { 11 9 return `${str}${num > 1 ? "s" : ""}`; ··· 59 57 { 60 58 name: "Open Moonbase", 61 59 onClick: () => { 62 - const { open } = spacepack.findByExports("setSection", "clearSubsection")[0].exports.Z; 60 + const { open } = spacepack.require("discord/actions/UserSettingsModalActionCreators").default; 63 61 if (MoonbaseSettingsStore.getExtensionConfigRaw<boolean>("moonbase", "sections", false)) { 64 62 open("moonbase-extensions"); 65 63 } else { 66 - MoonbaseSettingsStore.showOnlyUpdateable = true; 67 - open("moonbase", 0); 64 + open("moonbase", "0"); 68 65 } 69 66 return true; 70 67 }
+5
packages/core-extensions/src/moonbase/wp.d.ts
··· 5 5 declare module "@moonlight-mod/wp/moonbase_stores" { 6 6 export * from "core-extensions/src/moonbase/webpackModules/stores"; 7 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 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"; 2 6 7 + const logger = moonlightHost.getLogger("nativeFixes/host"); 3 8 const enabledFeatures = app.commandLine.getSwitchValue("enable-features").split(","); 4 9 5 10 moonlightHost.events.on("window-created", function (browserWindow) { ··· 22 27 23 28 // already added on Windows, but not on other operating systems 24 29 app.commandLine.appendSwitch("disable-background-timer-throttling"); 30 + } 31 + 32 + if (moonlightHost.getConfigOption<boolean>("nativeFixes", "vulkan") ?? false) { 33 + enabledFeatures.push("Vulkan", "DefaultANGLEVulkan", "VulkanFromANGLE"); 25 34 } 26 35 27 36 if (process.platform === "linux") { ··· 32 41 if (moonlightHost.getConfigOption<boolean>("nativeFixes", "linuxSpeechDispatcher") ?? true) { 33 42 app.commandLine.appendSwitch("enable-speech-dispatcher"); 34 43 } 44 + 45 + if (moonlightHost.getConfigOption<boolean>("nativeFixes", "linuxHevcSupport") ?? true) { 46 + enabledFeatures.push("PlatformHEVCDecoderSupport"); 47 + } 35 48 } 36 49 37 50 // NOTE: Only tested if this appears on Windows, it should appear on all when 38 51 // hardware acceleration is disabled 39 52 const noAccel = app.commandLine.hasSwitch("disable-gpu-compositing"); 40 53 if ((moonlightHost.getConfigOption<boolean>("nativeFixes", "vaapi") ?? true) && !noAccel) { 41 - if (process.platform === "linux") 54 + if (process.platform === "linux") { 42 55 // These will eventually be renamed https://source.chromium.org/chromium/chromium/src/+/5482210941a94d70406b8da962426e4faca7fce4 43 56 enabledFeatures.push("VaapiVideoEncoder", "VaapiVideoDecoder", "VaapiVideoDecodeLinuxGL"); 57 + 58 + if (moonlightHost.getConfigOption<boolean>("nativeFixes", "vaapiIgnoreDriverChecks") ?? false) 59 + enabledFeatures.push("VaapiIgnoreDriverChecks"); 60 + } 44 61 } 45 62 46 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 4 "meta": { 5 5 "name": "Native Fixes", 6 6 "tagline": "Various configurable fixes for Discord and Electron", 7 - "authors": ["Cynosphere", "adryd"], 7 + "authors": ["Cynosphere", "adryd", "NotNite"], 8 8 "tags": ["fixes"] 9 9 }, 10 10 "environment": "desktop", ··· 23 23 "type": "boolean", 24 24 "default": true 25 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 + }, 26 33 "linuxAutoscroll": { 27 34 "advice": "restart", 28 35 "displayName": "Enable middle click autoscroll on Linux", ··· 41 48 "advice": "restart", 42 49 "displayName": "Enable VAAPI features on Linux", 43 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", 44 72 "type": "boolean", 45 73 "default": true 46 74 }
+3 -3
packages/core-extensions/src/noHideToken/index.ts
··· 2 2 3 3 export const patches: Patch[] = [ 4 4 { 5 - find: "hideToken:function", 5 + find: "hideToken:()=>", 6 6 replace: { 7 - match: /(?<=hideToken:function\(\){)/, 8 - replacement: `return()=>{};` 7 + match: /hideToken:\(\)=>.+?,/, 8 + replacement: `hideToken:()=>{},` 9 9 } 10 10 } 11 11 ];
+3 -3
packages/core-extensions/src/noTrack/index.ts
··· 2 2 3 3 export const patches: Patch[] = [ 4 4 { 5 - find: "analyticsTrackingStoreMaker:function", 5 + find: "analyticsTrackingStoreMaker:()=>", 6 6 replace: { 7 - match: /analyticsTrackingStoreMaker:function\(\){return .+?}/, 8 - replacement: "analyticsTrackingStoreMaker:function(){return ()=>{}}" 7 + match: /analyticsTrackingStoreMaker:\(\)=>.+?,/, 8 + replacement: "analyticsTrackingStoreMaker:()=>()=>{}," 9 9 } 10 10 }, 11 11 {
+3 -1
packages/core-extensions/src/noTrack/manifest.json
··· 10 10 }, 11 11 "blocked": [ 12 12 "https://*.discord.com/api/v*/science", 13 - "https://*.discord.com/api/v*/metrics" 13 + "https://*.discord.com/api/v*/metrics", 14 + "https://*.discordapp.com/api/v*/science", 15 + "https://*.discordapp.com/api/v*/metrics" 14 16 ] 15 17 }
+3 -6
packages/core-extensions/src/notices/webpackModules/component.tsx
··· 1 1 import React from "@moonlight-mod/wp/react"; 2 2 import Dispatcher from "@moonlight-mod/wp/discord/Dispatcher"; 3 - import * as Components from "@moonlight-mod/wp/discord/components/common/index"; 3 + import { Notice, NoticeCloseButton, PrimaryCTANoticeButton } from "@moonlight-mod/wp/discord/components/common/index"; 4 4 import { useStateFromStoresObject } from "@moonlight-mod/wp/discord/packages/flux"; 5 5 import NoticesStore from "@moonlight-mod/wp/notices_notices"; 6 - import type { Notice } from "@moonlight-mod/types/coreExtensions/notices"; 6 + import type { Notice as NoticeType } from "@moonlight-mod/types/coreExtensions/notices"; 7 7 8 - // FIXME: types 9 - const { Notice, NoticeCloseButton, PrimaryCTANoticeButton } = Components; 10 - 11 - function popAndDismiss(notice: Notice) { 8 + function popAndDismiss(notice: NoticeType) { 12 9 NoticesStore.popNotice(); 13 10 if (notice?.onDismiss) { 14 11 notice.onDismiss();
+103 -15
packages/core-extensions/src/quietLoggers/index.ts
··· 3 3 const notXssDefensesOnly = () => 4 4 (moonlight.getConfigOption<boolean>("quietLoggers", "xssDefensesOnly") ?? false) === false; 5 5 6 + const silenceDiscordLogger = moonlight.getConfigOption<boolean>("quietLoggers", "silenceDiscordLogger") ?? false; 7 + 6 8 // These patches MUST run before the simple patches, these are to remove loggers 7 9 // that end up causing syntax errors by the normal patch 8 10 const loggerFixes: Patch[] = [ ··· 16 18 { 17 19 find: '("GatewaySocket")', 18 20 replace: { 19 - match: /.\.(info|log)(\(.+?\))(;|,)/g, 20 - replacement: (_, type, body, trail) => `(()=>{})${body}${trail}` 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: "(()=>{})(" 21 30 } 22 31 } 23 32 ]; ··· 28 37 // Patches to simply remove a logger call 29 38 const stubPatches = [ 30 39 // "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: ".+?\)\),/], 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"\),/], 41 49 [ 42 50 '"Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. Action: "', 43 - /.\.has\(.\.type\)&&.\.log\(.+?\.type\)\),/ 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\),/ 44 66 ], 45 - ['console.warn("Window state not initialized"', /console\.warn\("Window state not initialized",.\),/] 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")' 46 99 ]; 47 100 48 101 const simplePatches = [ ··· 54 107 { 55 108 find: ".Messages.SELF_XSS_HEADER", 56 109 replace: { 57 - match: /\(null!=.{1,2}&&"0\.0\.0"===.{1,2}\.remoteApp\.getVersion\(\)\)/, 110 + match: /\(null!=\i&&"0\.0\.0"===\i\.remoteApp\.getVersion\(\)\)/, 58 111 replacement: "(true)" 59 112 } 60 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 + }, 61 141 ...loggerFixes, 62 142 ...stubPatches.map((patch) => ({ 63 143 find: patch[0], ··· 72 152 replace: { 73 153 match: patch[0], 74 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: "(()=>{})(" 75 163 }, 76 164 prerequisite: notXssDefensesOnly 77 165 }))
+7
packages/core-extensions/src/quietLoggers/manifest.json
··· 15 15 "description": "Only disable self XSS prevention log", 16 16 "type": "boolean", 17 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 18 25 } 19 26 } 20 27 }
+2 -1
packages/core-extensions/src/rocketship/manifest.json
··· 7 7 "name": "Rocketship", 8 8 "tagline": "Adds new features when using rocketship", 9 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"] 10 + "authors": ["NotNite", "Cynosphere", "adryd"], 11 + "deprecated": true 11 12 } 12 13 }
+1 -1
packages/core-extensions/src/settings/index.ts
··· 12 12 { 13 13 find: 'navId:"user-settings-cog",', 14 14 replace: { 15 - match: /children:\[(.)\.map\(.+?\),children:.\((.)\)/, 15 + match: /children:\[(\i)\.map\(.+?\),.*?children:\i\((\i)\)/, 16 16 replacement: (orig, sections, section) => 17 17 `${orig.replace( 18 18 /Object\.values\(.\..+?\)/,
+8 -2
packages/core-extensions/src/settings/webpackModules/settings.ts
··· 1 1 import { SettingsSection, Settings as SettingsType } from "@moonlight-mod/types/coreExtensions/settings"; 2 + import UserSettingsModalActionCreators from "@moonlight-mod/wp/discord/actions/UserSettingsModalActionCreators"; 2 3 3 4 export const Settings: SettingsType = { 4 5 ourSections: [], 5 6 sectionNames: [], 6 7 sectionMenuItems: {}, 7 8 8 - addSection: (section, label, element, color = null, pos, notice) => { 9 + addSection: (section, label, element, color = null, pos, notice, onClick) => { 9 10 const data: SettingsSection = { 10 11 section, 11 12 label, 12 13 color, 13 14 element, 14 15 pos: pos ?? -4, 15 - notice: notice 16 + notice: notice, 17 + onClick: onClick ?? (() => UserSettingsModalActionCreators.open(section)) 16 18 }; 17 19 18 20 Settings.ourSections.push(data); ··· 43 45 44 46 _mutateSections: (sections) => { 45 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 + } 46 52 sections.splice(section.pos < 0 ? sections.length + section.pos : section.pos, 0, section); 47 53 } 48 54
+73 -16
packages/core-extensions/src/spacepack/webpackModules/spacepack.ts
··· 37 37 "module", 38 38 "exports", 39 39 "require", 40 - `(${funcStr}).apply(this, arguments)\n` + `//# sourceURL=Webpack-Module-${module}` 40 + `(${funcStr}).apply(this, arguments)\n` + `//# sourceURL=Webpack-Module/${module.slice(0, 3)}/${module}` 41 41 ) as WebpackModuleFunc; 42 42 }, 43 43 44 44 findByCode: (...args: (string | RegExp)[]) => { 45 - return Object.entries(modules) 45 + const ret = Object.entries(modules) 46 46 .filter(([id, mod]) => !args.some((item) => !testFind(mod.toString(), processFind(item)))) 47 47 .map(([id]) => { 48 48 //if (!(id in cache)) require(id); ··· 52 52 try { 53 53 exports = require(id); 54 54 } catch (e) { 55 - logger.error(`Error requiring module "${id}": `, e); 55 + logger.error(`findByCode: Error requiring module "${id}": `, args, e); 56 56 } 57 57 58 58 return { ··· 61 61 }; 62 62 }) 63 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; 64 70 }, 65 71 66 72 findByExports: (...args: string[]) => { ··· 84 90 }, 85 91 86 92 findObjectFromKey: (exports: Record<string, any>, key: string) => { 93 + let ret = null; 87 94 let subKey; 88 95 if (key.indexOf(".") > -1) { 89 96 const splitKey = key.split("."); ··· 94 101 const obj = exports[exportKey]; 95 102 if (obj && obj[key] !== undefined) { 96 103 if (subKey) { 97 - if (obj[key][subKey]) return obj; 104 + if (obj[key][subKey]) { 105 + ret = obj; 106 + break; 107 + } 98 108 } else { 99 - return obj; 109 + ret = obj; 110 + break; 100 111 } 101 112 } 102 113 } 103 - return null; 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; 104 120 }, 105 121 106 122 findObjectFromValue: (exports: Record<string, any>, value: any) => { 123 + let ret = null; 107 124 for (const exportKey in exports) { 108 125 const obj = exports[exportKey]; 109 126 // eslint-disable-next-line eqeqeq 110 - if (obj == value) return obj; 127 + if (obj == value) { 128 + ret = obj; 129 + break; 130 + } 111 131 for (const subKey in obj) { 112 132 // eslint-disable-next-line eqeqeq 113 133 if (obj && obj[subKey] == value) { 114 - return obj; 134 + ret = obj; 135 + break; 115 136 } 116 137 } 117 138 } 118 - return null; 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; 119 145 }, 120 146 121 147 findObjectFromKeyValuePair: (exports: Record<string, any>, key: string, value: any) => { 148 + let ret = null; 122 149 for (const exportKey in exports) { 123 150 const obj = exports[exportKey]; 124 151 // eslint-disable-next-line eqeqeq 125 152 if (obj && obj[key] == value) { 126 - return obj; 153 + ret = obj; 154 + break; 127 155 } 128 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 + 129 169 return null; 130 170 }, 131 171 132 172 findFunctionByStrings: (exports: Record<string, any>, ...strings: (string | RegExp)[]) => { 133 - return ( 173 + const ret = 134 174 Object.entries(exports).filter( 135 175 ([index, func]) => 136 176 typeof func === "function" && !strings.some((query) => !testFind(func.toString(), processFind(query))) 137 - )?.[0]?.[1] ?? null 138 - ); 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; 139 184 }, 140 185 141 186 lazyLoad: (find: string | RegExp | (string | RegExp)[], chunk: RegExp, module: RegExp) => { 187 + chunk = processFind(chunk); 188 + module = processFind(module); 189 + 142 190 const mod = Array.isArray(find) ? spacepack.findByCode(...find) : spacepack.findByCode(find); 143 - if (mod.length < 1) return Promise.reject("Module find failed"); 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 + } 144 195 145 196 const findId = mod[0].id; 146 197 const findCode = webpackRequire.m[findId].toString().replace(/\n/g, ""); ··· 153 204 if (match) chunkIds = [...match[0].matchAll(/"(\d+)"/g)].map(([, id]) => id); 154 205 } 155 206 156 - if (!chunkIds || chunkIds.length === 0) return Promise.reject("Chunk ID match failed"); 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 + } 157 211 158 212 const moduleId = findCode.match(module)?.[1]; 159 - if (!moduleId) return Promise.reject("Module ID match failed"); 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 + } 160 217 161 218 return Promise.all(chunkIds.map((c) => webpackRequire.e(c))).then(() => webpackRequire(moduleId)); 162 219 },
+4 -1
packages/core-extensions/tsconfig.json
··· 1 1 { 2 - "extends": "../../tsconfig.json" 2 + "extends": "../../tsconfig.json", 3 + "compilerOptions": { 4 + "lib": ["ESNext", "DOM", "DOM.Iterable"] 5 + } 3 6 }
+10 -3
packages/injector/package.json
··· 1 1 { 2 2 "name": "@moonlight-mod/injector", 3 3 "private": true, 4 + "engines": { 5 + "node": ">=22", 6 + "pnpm": ">=10", 7 + "npm": "pnpm", 8 + "yarn": "pnpm" 9 + }, 4 10 "dependencies": { 5 - "@moonlight-mod/types": "workspace:*", 6 - "@moonlight-mod/core": "workspace:*" 7 - } 11 + "@moonlight-mod/core": "workspace:*", 12 + "@moonlight-mod/types": "workspace:*" 13 + }, 14 + "engineStrict": true 8 15 }
+37 -14
packages/injector/src/index.ts
··· 76 76 blockedUrls = compiled; 77 77 }); 78 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 - ]; 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"]; 90 81 const values = ["*", "blob:", "data:", "'unsafe-inline'", "'unsafe-eval'", "disclip:"]; 91 82 92 83 const csp = "content-security-policy"; ··· 106 97 parts[directive] = values; 107 98 } 108 99 100 + for (const [directive, urls] of Object.entries(extensionCspOverrides)) { 101 + parts[directive] ??= []; 102 + parts[directive].push(...urls); 103 + } 104 + 109 105 const stringified = Object.entries<string[]>(parts) 110 106 .map(([key, value]) => { 111 107 return `${key} ${value.join(" ")}`; ··· 131 127 // Event for when a window is created 132 128 moonlightHost.events.emit("window-created", this, isMainWindow); 133 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 + 134 142 this.webContents.session.webRequest.onHeadersReceived((details, cb) => { 135 143 if (details.responseHeaders != null) { 136 144 // Patch CSP so things can use externally hosted assets 137 145 if (details.resourceType === "mainFrame") { 138 - patchCsp(details.responseHeaders); 146 + patchCsp(details.responseHeaders, extensionCspOverrides); 139 147 } 140 148 141 149 // Allow plugins to bypass CORS for specific URLs 142 150 if (corsAllow.some((x) => details.url.startsWith(x))) { 143 - details.responseHeaders["access-control-allow-origin"] = ["*"]; 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] = ["*"]; 144 158 } 159 + 160 + moonlightHost.events.emit("headers-received", details, isMainWindow); 145 161 146 162 cb({ cancel: false, responseHeaders: details.responseHeaders }); 147 163 } ··· 160 176 with esbuild someday). 161 177 */ 162 178 if (details.resourceType === "script" && isMainWindow) { 163 - const hasUrl = scriptUrls.some((url) => details.url.includes(url) && !details.url.includes("?inj")); 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 + }); 164 187 if (hasUrl) blockedScripts.add(details.url); 165 188 166 189 if (blockedScripts.size === scriptUrls.length) {
+8 -1
packages/node-preload/package.json
··· 1 1 { 2 2 "name": "@moonlight-mod/node-preload", 3 3 "private": true, 4 + "engines": { 5 + "node": ">=22", 6 + "pnpm": ">=10", 7 + "npm": "pnpm", 8 + "yarn": "pnpm" 9 + }, 4 10 "dependencies": { 5 11 "@moonlight-mod/core": "workspace:*", 6 12 "@moonlight-mod/types": "workspace:*" 7 - } 13 + }, 14 + "engineStrict": true 8 15 }
+52 -37
packages/node-preload/src/index.ts
··· 11 11 import createFS from "@moonlight-mod/core/fs"; 12 12 import { registerCors, registerBlocked, getDynamicCors } from "@moonlight-mod/core/cors"; 13 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"; 14 16 15 17 let initialized = false; 16 18 let logger: Logger; ··· 51 53 processedExtensions, 52 54 nativesCache: {}, 53 55 isBrowser: false, 56 + events: createEventEmitter<NodeEventType, NodeEventPayloads>(), 54 57 55 58 version: MOONLIGHT_VERSION, 56 59 branch: MOONLIGHT_BRANCH as MoonlightBranch, ··· 62 65 const manifest = getManifest(extensions, ext); 63 66 return getConfigOption(ext, name, config, manifest?.settings); 64 67 }, 65 - setConfigOption(ext, name, value) { 68 + async setConfigOption(ext, name, value) { 66 69 setConfigOption(config, ext, name, value); 67 - this.writeConfig(config); 70 + await this.writeConfig(config); 68 71 }, 69 72 async writeConfig(newConfig) { 70 73 await writeConfig(newConfig); 71 74 config = newConfig; 75 + this.events.dispatchEvent(NodeEventType.ConfigSaved, newConfig); 72 76 }, 73 77 74 78 getNatives: (ext: string) => global.moonlightNode.nativesCache[ext], ··· 129 133 } 130 134 } 131 135 132 - ipcRenderer.on(constants.ipcNodePreloadKickoff, (_, blockedScripts: string[]) => { 133 - (async () => { 134 - try { 135 - await init(); 136 - logger.debug("Blocked scripts:", blockedScripts); 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); 137 151 138 - const oldPreloadPath: string = ipcRenderer.sendSync(constants.ipcGetOldPreloadPath); 139 - logger.debug("Old preload path:", oldPreloadPath); 140 - if (oldPreloadPath) require(oldPreloadPath); 152 + const oldPreloadPath: string = ipcRenderer.sendSync(constants.ipcGetOldPreloadPath); 153 + logger.debug("Old preload path:", oldPreloadPath); 154 + if (oldPreloadPath) require(oldPreloadPath); 141 155 142 - // Do this to get global.DiscordNative assigned 143 - // @ts-expect-error Lying to discord_desktop_core 144 - process.emit("loaded"); 156 + // Do this to get global.DiscordNative assigned 157 + // @ts-expect-error Lying to discord_desktop_core 158 + process.emit("loaded"); 145 159 146 - function replayScripts() { 147 - const scripts = [...document.querySelectorAll("script")].filter( 148 - (script) => script.src && blockedScripts.some((url) => url.includes(script.src)) 149 - ); 160 + function replayScripts() { 161 + const scripts = [...document.querySelectorAll("script")].filter( 162 + (script) => script.src && blockedScripts.some((url) => url.includes(script.src)) 163 + ); 150 164 151 - blockedScripts.reverse(); 152 - for (const url of blockedScripts) { 153 - if (url.includes("/sentry.")) continue; 165 + blockedScripts.reverse(); 166 + for (const url of blockedScripts) { 167 + if (url.includes("/sentry.")) continue; 154 168 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); 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); 160 177 } 161 - script.remove(); 162 - document.documentElement.appendChild(newScript); 163 178 } 164 - } 165 179 166 - if (document.readyState === "complete") { 167 - replayScripts(); 168 - } else { 169 - window.addEventListener("load", replayScripts); 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); 170 187 } 171 - } catch (e) { 172 - logger.error("Error restoring original scripts:", e); 173 - } 174 - })(); 175 - }); 188 + })(); 189 + }); 190 + }
+4 -1
packages/node-preload/tsconfig.json
··· 1 1 { 2 - "extends": "../../tsconfig.json" 2 + "extends": "../../tsconfig.json", 3 + "compilerOptions": { 4 + "lib": ["DOM", "ESNext", "DOM.Iterable"] 5 + } 3 6 }
+14 -7
packages/types/package.json
··· 1 1 { 2 2 "name": "@moonlight-mod/types", 3 - "version": "1.3.4", 4 - "main": "./src/index.ts", 5 - "types": "./src/index.ts", 3 + "version": "1.3.17", 6 4 "exports": { 7 5 ".": "./src/index.ts", 8 6 "./import": "./src/import.d.ts", 9 7 "./*": "./src/*.ts" 10 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 + }, 11 18 "dependencies": { 12 - "@moonlight-mod/lunast": "^1.0.0", 13 - "@moonlight-mod/mappings": "^1.0.10", 14 - "@moonlight-mod/moonmap": "^1.0.3", 19 + "@moonlight-mod/lunast": "^1.0.1", 20 + "@moonlight-mod/mappings": "^1.1.25", 21 + "@moonlight-mod/moonmap": "^1.0.5", 15 22 "@types/react": "^18.3.10", 16 - "csstype": "^3.1.2", 23 + "csstype": "^3.1.3", 17 24 "standalone-electron-types": "^1.0.0" 18 25 } 19 26 }
+41
packages/types/src/config.ts
··· 33 33 }; 34 34 35 35 export type BooleanSettingType = { 36 + /** 37 + * Displays as a simple switch. 38 + */ 36 39 type: ExtensionSettingType.Boolean; 37 40 default?: boolean; 38 41 }; 39 42 40 43 export type NumberSettingType = { 44 + /** 45 + * Displays as a simple slider. 46 + */ 41 47 type: ExtensionSettingType.Number; 42 48 default?: number; 43 49 min?: number; ··· 45 51 }; 46 52 47 53 export type StringSettingType = { 54 + /** 55 + * Displays as a single line string input. 56 + */ 48 57 type: ExtensionSettingType.String; 49 58 default?: string; 50 59 }; 51 60 52 61 export type MultilineTextInputSettingType = { 62 + /** 63 + * Displays as a multiple line string input. 64 + */ 53 65 type: ExtensionSettingType.MultilineString; 54 66 default?: string; 55 67 }; 56 68 57 69 export type SelectSettingType = { 70 + /** 71 + * A dropdown to pick between one of many values. 72 + */ 58 73 type: ExtensionSettingType.Select; 59 74 options: SelectOption[]; 60 75 default?: string; 61 76 }; 62 77 63 78 export type MultiSelectSettingType = { 79 + /** 80 + * A dropdown to pick multiple values. 81 + */ 64 82 type: ExtensionSettingType.MultiSelect; 65 83 options: string[]; 66 84 default?: string[]; 67 85 }; 68 86 69 87 export type ListSettingType = { 88 + /** 89 + * A list of strings that the user can add or remove from. 90 + */ 70 91 type: ExtensionSettingType.List; 71 92 default?: string[]; 72 93 }; 73 94 74 95 export type DictionarySettingType = { 96 + /** 97 + * A dictionary (key-value pair) that the user can add or remove from. 98 + */ 75 99 type: ExtensionSettingType.Dictionary; 76 100 default?: Record<string, string>; 77 101 }; 78 102 79 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 + */ 80 108 type: ExtensionSettingType.Custom; 81 109 default?: any; 82 110 }; ··· 88 116 } 89 117 90 118 export type ExtensionSettingsManifest = { 119 + /** 120 + * A human friendly name for the setting. 121 + */ 91 122 displayName?: string; 123 + 124 + /** 125 + * A longer description for the setting. 126 + * Markdown is not supported. 127 + */ 92 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 + */ 93 134 advice?: ExtensionSettingsAdvice; 94 135 } & ( 95 136 | BooleanSettingType
+13 -4
packages/types/src/core/event.ts
··· 1 + import { Config } from "../config"; 1 2 import { WebpackModuleFunc, WebpackRequireType } from "../discord"; 2 3 3 4 export interface MoonlightEventEmitter<EventId extends string = string, EventData = Record<EventId, any>> { ··· 6 7 removeEventListener: <Id extends keyof EventData>(id: Id, cb: (data: EventData[Id]) => void) => void; 7 8 } 8 9 9 - export enum EventType { 10 + export enum WebEventType { 10 11 ChunkLoad = "chunkLoad", 11 12 ExtensionLoad = "extensionLoad" 12 13 } 13 14 14 - export type EventPayloads = { 15 - [EventType.ChunkLoad]: { 15 + export type WebEventPayloads = { 16 + [WebEventType.ChunkLoad]: { 16 17 chunkId?: number[]; 17 18 modules: { [id: string]: WebpackModuleFunc }; 18 19 require?: (require: WebpackRequireType) => any; 19 20 }; 20 - [EventType.ExtensionLoad]: string; 21 + [WebEventType.ExtensionLoad]: string; 22 + }; 23 + 24 + export enum NodeEventType { 25 + ConfigSaved = "configSaved" 26 + } 27 + 28 + export type NodeEventPayloads = { 29 + [NodeEventType.ConfigSaved]: Config; 21 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
+2 -2
packages/types/src/coreExtensions/contextMenu.ts
··· 14 14 * Registers a new context menu item for a given context menu type. 15 15 * @param navId The navigation ID for the target context menu (e.g. "user-context", "message") 16 16 * @param item A React component 17 - * @param anchorId An existing item's ID to anchor the new item to 17 + * @param anchor An existing item's ID to anchor the new item to 18 18 * @param before Whether to insert the new item before the anchor item 19 19 */ 20 - addItem: (navId: string, item: React.FC<any>, anchorId: string, before?: boolean) => void; 20 + addItem: (navId: string, item: React.FC<any>, anchor: string | RegExp, before?: boolean) => void; 21 21 22 22 MenuCheckboxItem: MenuCheckboxItem; 23 23 MenuControlItem: MenuControlItem;
+1 -1
packages/types/src/coreExtensions/notices.ts
··· 1 - import type { Store } from "@moonlight-mod/mappings/discord/packages/flux"; 1 + import type { Store } from "@moonlight-mod/mappings/discord/packages/flux/Store"; 2 2 3 3 export type NoticeButton = { 4 4 name: string;
+11 -8
packages/types/src/coreExtensions/settings.ts
··· 1 1 import React, { ReactElement } from "react"; 2 - import type { Store } from "@moonlight-mod/mappings/discord/packages/flux"; 2 + import type { Store } from "@moonlight-mod/mappings/discord/packages/flux/Store"; 3 3 4 4 export type NoticeProps = { 5 5 stores: Store<any>[]; ··· 7 7 }; 8 8 9 9 export type SettingsSection = 10 - | { section: "DIVIDER"; pos: number } 11 - | { section: "HEADER"; label: string; pos: number } 10 + | { section: "DIVIDER"; pos: number | ((sections: SettingsSection[]) => number) } 11 + | { section: "HEADER"; label: string; pos: number | ((sections: SettingsSection[]) => number) } 12 12 | { 13 13 section: string; 14 14 label: string; 15 15 color: string | null; 16 16 element: React.FunctionComponent; 17 - pos: number; 17 + pos: number | ((sections: SettingsSection[]) => number); 18 18 notice?: NoticeProps; 19 + onClick?: () => void; 19 20 _moonlight_submenu?: () => ReactElement | ReactElement[]; 20 21 }; 21 22 ··· 32 33 * @param color A color to use for the section 33 34 * @param pos The position in the settings menu to place the section 34 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 35 37 */ 36 38 addSection: ( 37 39 section: string, 38 40 label: string, 39 41 element: React.FunctionComponent, 40 42 color?: string | null, 41 - pos?: number, 42 - notice?: NoticeProps 43 + pos?: number | ((sections: SettingsSection[]) => number), 44 + notice?: NoticeProps, 45 + onClick?: () => void 43 46 ) => void; 44 47 45 48 /** ··· 53 56 * Places a divider in the settings menu. 54 57 * @param pos The position in the settings menu to place the divider 55 58 */ 56 - addDivider: (pos: number | null) => void; 59 + addDivider: (pos: number | ((sections: SettingsSection[]) => number) | null) => void; 57 60 58 61 /** 59 62 * Places a header in the settings menu. 60 63 * @param pos The position in the settings menu to place the header 61 64 */ 62 - addHeader: (label: string, pos: number | null) => void; 65 + addHeader: (label: string, pos: number | ((sections: SettingsSection[]) => number) | null) => void; 63 66 64 67 /** 65 68 * @private
+1
packages/types/src/coreExtensions/spacepack.ts
··· 18 18 19 19 /** 20 20 * Find Webpack modules based on their exports. 21 + * @deprecated This has race conditions. Consider using findByCode instead. 21 22 * @param args A list of finds to match exports against 22 23 * @returns The Webpack modules, if found 23 24 */
+3
packages/types/src/coreExtensions.ts
··· 5 5 export * as Notices from "./coreExtensions/notices"; 6 6 export * as Moonbase from "./coreExtensions/moonbase"; 7 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 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"; 2 5 import { ContextMenu, EvilItemParser } from "../coreExtensions/contextMenu"; 3 6 import { Markdown } from "../coreExtensions/markdown"; 4 7 import { Moonbase } from "../coreExtensions/moonbase"; ··· 9 12 declare function WebpackRequire(id: string): any; 10 13 11 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; 12 24 13 25 declare function WebpackRequire(id: "contextMenu_evilMenu"): EvilItemParser; 14 26 declare function WebpackRequire(id: "contextMenu_contextMenu"): ContextMenu;
+101 -1
packages/types/src/extension.ts
··· 28 28 }; 29 29 30 30 export type ExtensionManifest = { 31 + $schema?: string; 32 + 33 + /** 34 + * A unique identifier for your extension. 35 + */ 31 36 id: string; 37 + 38 + /** 39 + * A version string for your extension - doesn't need to follow a specific format. Required for publishing. 40 + */ 32 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 + */ 33 46 apiLevel?: number; 47 + 48 + /** 49 + * Which environment this extension is capable of running in. 50 + */ 34 51 environment?: ExtensionEnvironment; 35 52 53 + /** 54 + * Metadata about your extension for use in Moonbase. 55 + */ 36 56 meta?: { 57 + /** 58 + * A human friendly name for your extension as a proper noun. 59 + */ 37 60 name?: string; 61 + 62 + /** 63 + * A short tagline that appears below the name. 64 + */ 38 65 tagline?: string; 66 + 67 + /** 68 + * A longer description that can use Markdown. 69 + */ 39 70 description?: string; 71 + 72 + /** 73 + * List of authors that worked on this extension - accepts string or object with ID. 74 + */ 40 75 authors?: ExtensionAuthor[]; 41 - deprecated?: boolean; 76 + 77 + /** 78 + * A list of tags that are relevant to the extension. 79 + */ 42 80 tags?: ExtensionTag[]; 81 + 82 + /** 83 + * The URL to the source repository. 84 + */ 43 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 + */ 44 96 changelog?: string; 97 + 98 + /** 99 + * Whether the extension is deprecated and no longer receiving updates. 100 + */ 101 + deprecated?: boolean; 45 102 }; 46 103 104 + /** 105 + * A list of extension IDs that are required for the extension to load. 106 + */ 47 107 dependencies?: string[]; 108 + 109 + /** 110 + * A list of extension IDs that the user may want to install. 111 + */ 48 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 + */ 49 118 incompatible?: string[]; 50 119 120 + /** 121 + * A list of settings for your extension, where the key is the settings ID. 122 + */ 51 123 settings?: Record<string, ExtensionSettingsManifest>; 52 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 + */ 53 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 + */ 54 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[]>; 55 144 }; 56 145 57 146 export enum ExtensionEnvironment { 147 + /** 148 + * The extension will run on both platforms, the host/native modules MAY be loaded 149 + */ 58 150 Both = "both", 151 + 152 + /** 153 + * Extension will run on desktop only, the host/native modules are guaranteed to load 154 + */ 59 155 Desktop = "desktop", 156 + 157 + /** 158 + * Currently equivalent to Both 159 + */ 60 160 Web = "web" 61 161 } 62 162
+1
packages/types/src/fs.ts
··· 15 15 16 16 join: (...parts: string[]) => string; 17 17 dirname: (path: string) => string; 18 + basename: (path: string) => string; 18 19 };
+11 -4
packages/types/src/globals.ts
··· 4 4 import type EventEmitter from "events"; 5 5 import type LunAST from "@moonlight-mod/lunast"; 6 6 import type Moonmap from "@moonlight-mod/moonmap"; 7 - import type { EventPayloads, EventType, MoonlightEventEmitter } from "./core/event"; 8 - import { MoonlightFS } from "./fs"; 7 + import type { 8 + WebEventPayloads, 9 + WebEventType, 10 + MoonlightEventEmitter, 11 + NodeEventType, 12 + NodeEventPayloads 13 + } from "./core/event"; 14 + import type { MoonlightFS } from "./fs"; 9 15 10 16 export type MoonlightHost = { 11 17 config: Config; ··· 34 40 processedExtensions: ProcessedExtensions; 35 41 nativesCache: Record<string, any>; 36 42 isBrowser: boolean; 43 + events: MoonlightEventEmitter<NodeEventType, NodeEventPayloads>; 37 44 38 45 version: string; 39 46 branch: MoonlightBranch; 40 47 41 48 getConfig: (ext: string) => ConfigExtension["config"]; 42 49 getConfigOption: <T>(ext: string, name: string) => T | undefined; 43 - setConfigOption: <T>(ext: string, name: string, value: T) => void; 50 + setConfigOption: <T>(ext: string, name: string, value: T) => Promise<void>; 44 51 writeConfig: (config: Config) => Promise<void>; 45 52 46 53 getNatives: (ext: string) => any | undefined; ··· 60 67 unpatched: Set<IdentifiedPatch>; 61 68 pendingModules: Set<IdentifiedWebpackModule>; 62 69 enabledExtensions: Set<string>; 63 - events: MoonlightEventEmitter<EventType, EventPayloads>; 70 + events: MoonlightEventEmitter<WebEventType, WebEventPayloads>; 64 71 patchingInternals: { 65 72 onModuleLoad: (moduleId: string | string[], callback: (moduleId: string) => void) => void; 66 73 registerPatch: (patch: IdentifiedPatch) => void;
+32
packages/types/src/import.d.ts
··· 4 4 export = AppPanels; 5 5 } 6 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 + } 7 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 + } 8 40 9 41 declare module "@moonlight-mod/wp/contextMenu_evilMenu" { 10 42 import { CoreExtensions } from "@moonlight-mod/types";
+1
packages/types/src/index.ts
··· 32 32 var moonlightNode: MoonlightNode; 33 33 var moonlightNodeSandboxed: MoonlightNodeSandboxed; 34 34 var moonlight: MoonlightWeb; 35 + var _moonlight_coreExtensionsStr: string; 35 36 36 37 var _moonlightBrowserInit: undefined | (() => Promise<void>); 37 38 var _moonlightWebLoad: undefined | (() => Promise<void>);
+841 -25
packages/types/src/mappings.d.ts
··· 1 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 + 2 39 declare module "@moonlight-mod/wp/discord/Dispatcher" { 3 40 import { MappedModules } from "@moonlight-mod/mappings"; 4 - const _: MappedModules["discord/Dispatcher"]; 5 - export = _; 41 + const _default: MappedModules["discord/Dispatcher"]["default"]; 42 + export default _default; 6 43 } 7 44 8 45 declare module "@moonlight-mod/wp/discord/actions/ContextMenuActionCreators" { 9 46 import { MappedModules } from "@moonlight-mod/mappings"; 10 - const _: MappedModules["discord/actions/ContextMenuActionCreators"]; 11 - export = _; 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"]; 12 160 } 13 161 14 162 declare module "@moonlight-mod/wp/discord/components/common/index" { 15 163 import { MappedModules } from "@moonlight-mod/mappings"; 16 - const _: MappedModules["discord/components/common/index"]; 17 - export = _; 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"]; 18 275 } 19 276 20 - declare module "@moonlight-mod/wp/discord/modules/guild_settings/IntegrationCard.css" { 277 + declare module "@moonlight-mod/wp/discord/components/modals/ConfirmModal" { 21 278 import { MappedModules } from "@moonlight-mod/mappings"; 22 - const _: MappedModules["discord/modules/guild_settings/IntegrationCard.css"]; 23 - export = _; 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"]; 24 503 } 25 504 26 505 declare module "@moonlight-mod/wp/discord/modules/markup/MarkupUtils" { 27 506 import { MappedModules } from "@moonlight-mod/mappings"; 28 - const _: MappedModules["discord/modules/markup/MarkupUtils"]; 29 - export = _; 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"]; 30 613 } 31 614 32 - declare module "@moonlight-mod/wp/discord/modules/user_settings/web/openUserSettings" { 615 + declare module "@moonlight-mod/wp/discord/modules/modals/Modals" { 33 616 import { MappedModules } from "@moonlight-mod/mappings"; 34 - const _: MappedModules["discord/modules/user_settings/web/openUserSettings"]; 35 - export = _; 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"]; 36 666 } 37 667 38 668 declare module "@moonlight-mod/wp/discord/packages/flux" { 39 669 import { MappedModules } from "@moonlight-mod/mappings"; 40 - const _: MappedModules["discord/packages/flux"]; 41 - export = _; 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"]; 42 747 } 43 748 44 749 declare module "@moonlight-mod/wp/discord/uikit/Flex" { 45 750 import { MappedModules } from "@moonlight-mod/mappings"; 46 - const _: MappedModules["discord/uikit/Flex"]; 47 - export = _; 751 + const _default: MappedModules["discord/uikit/Flex"]["default"]; 752 + export default _default; 48 753 } 49 754 50 755 declare module "@moonlight-mod/wp/discord/utils/ClipboardUtils" { 51 756 import { MappedModules } from "@moonlight-mod/mappings"; 52 - const _: MappedModules["discord/utils/ClipboardUtils"]; 53 - export = _; 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"]; 54 765 } 55 766 56 767 declare module "@moonlight-mod/wp/discord/utils/HTTPUtils" { 57 768 import { MappedModules } from "@moonlight-mod/mappings"; 58 - const _: MappedModules["discord/utils/HTTPUtils"]; 59 - export = _; 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"]; 60 776 } 61 777 62 778 declare module "@moonlight-mod/wp/discord/utils/NativeUtils" { 63 779 import { MappedModules } from "@moonlight-mod/mappings"; 64 - const _: MappedModules["discord/utils/NativeUtils"]; 65 - export = _; 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"]; 66 880 } 67 881 68 882 declare module "@moonlight-mod/wp/react" { 69 883 import { MappedModules } from "@moonlight-mod/mappings"; 70 - const _: MappedModules["react"]; 884 + const _: Omit<MappedModules["react"], "__mappings_exportEquals">; 71 885 export = _; 72 886 } 887 + 888 + declare module "@moonlight-mod/wp/uuid/v4" {}
+7 -7
packages/types/tsconfig.json
··· 1 1 { 2 2 "compilerOptions": { 3 - "target": "es2016", 4 - "module": "es6", 5 - "esModuleInterop": true, 6 - "forceConsistentCasingInFileNames": true, 7 - "strict": true, 8 - "moduleResolution": "bundler", 3 + "target": "ES2016", 9 4 "jsx": "react", 10 - "declaration": true 5 + "module": "ES6", 6 + "moduleResolution": "bundler", 7 + "strict": true, 8 + "declaration": true, 9 + "esModuleInterop": true, 10 + "forceConsistentCasingInFileNames": true 11 11 }, 12 12 "include": ["./src/**/*", "src/index.ts", "./src/import.d.ts"] 13 13 }
+10 -3
packages/web-preload/package.json
··· 2 2 "name": "@moonlight-mod/web-preload", 3 3 "private": true, 4 4 "main": "src/index.ts", 5 + "engineStrict": true, 6 + "engines": { 7 + "node": ">=22", 8 + "pnpm": ">=10", 9 + "npm": "pnpm", 10 + "yarn": "pnpm" 11 + }, 5 12 "dependencies": { 6 13 "@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", 14 + "@moonlight-mod/lunast": "catalog:prod", 15 + "@moonlight-mod/mappings": "catalog:prod", 16 + "@moonlight-mod/moonmap": "catalog:prod", 10 17 "@moonlight-mod/types": "workspace:*" 11 18 } 12 19 }
+2 -2
packages/web-preload/src/index.ts
··· 7 7 import Moonmap from "@moonlight-mod/moonmap"; 8 8 import loadMappings from "@moonlight-mod/mappings"; 9 9 import { createEventEmitter } from "@moonlight-mod/core/util/event"; 10 - import { EventPayloads, EventType } from "@moonlight-mod/types/core/event"; 10 + import { WebEventPayloads, WebEventType } from "@moonlight-mod/types/core/event"; 11 11 12 12 async function load() { 13 13 delete window._moonlightWebLoad; ··· 20 20 pendingModules: new Set(), 21 21 enabledExtensions: new Set(), 22 22 23 - events: createEventEmitter<EventType, EventPayloads>(), 23 + events: createEventEmitter<WebEventType, WebEventPayloads>(), 24 24 patchingInternals: { 25 25 onModuleLoad, 26 26 registerPatch,
+4 -1
packages/web-preload/tsconfig.json
··· 1 1 { 2 - "extends": "../../tsconfig.json" 2 + "extends": "../../tsconfig.json", 3 + "compilerOptions": { 4 + "lib": ["ESNext", "DOM"] 5 + } 3 6 }
+1243 -729
pnpm-lock.yaml
··· 4 4 autoInstallPeers: true 5 5 excludeLinksFromLockfile: false 6 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 + 7 62 importers: 8 63 9 64 .: 10 65 devDependencies: 11 66 '@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) 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 14 72 esbuild: 15 - specifier: ^0.19.3 73 + specifier: catalog:dev 16 74 version: 0.19.3 17 75 esbuild-copy-static-files: 18 - specifier: ^0.1.0 76 + specifier: catalog:dev 19 77 version: 0.1.0 20 78 eslint: 21 - specifier: ^9.12.0 22 - version: 9.12.0 79 + specifier: catalog:dev 80 + version: 9.23.0(jiti@2.4.2) 23 81 husky: 24 - specifier: ^8.0.3 82 + specifier: catalog:dev 25 83 version: 8.0.3 26 84 prettier: 27 - specifier: ^3.1.0 85 + specifier: catalog:dev 28 86 version: 3.1.0 87 + taze: 88 + specifier: catalog:dev 89 + version: 19.0.4 29 90 typescript: 30 - specifier: ^5.3.2 31 - version: 5.3.2 91 + specifier: catalog:dev 92 + version: 5.8.2 32 93 33 94 packages/browser: 34 95 dependencies: ··· 42 103 specifier: workspace:* 43 104 version: link:../web-preload 44 105 '@zenfs/core': 45 - specifier: ^1.0.2 46 - version: 1.0.2 106 + specifier: catalog:prod 107 + version: 2.0.0 47 108 '@zenfs/dom': 48 - specifier: ^0.2.16 49 - version: 0.2.16(@zenfs/core@1.0.2) 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 50 115 51 116 packages/core: 52 117 dependencies: ··· 63 128 specifier: workspace:* 64 129 version: link:../types 65 130 microdiff: 66 - specifier: ^1.5.0 131 + specifier: catalog:prod 67 132 version: 1.5.0 68 133 nanotar: 69 - specifier: ^0.1.1 134 + specifier: catalog:prod 70 135 version: 0.1.1 71 136 72 137 packages/injector: ··· 90 155 packages/types: 91 156 dependencies: 92 157 '@moonlight-mod/lunast': 93 - specifier: ^1.0.0 94 - version: 1.0.0 158 + specifier: ^1.0.1 159 + version: 1.0.1 95 160 '@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) 161 + specifier: ^1.1.25 162 + version: 1.1.25(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5) 98 163 '@moonlight-mod/moonmap': 99 - specifier: ^1.0.3 100 - version: 1.0.3 164 + specifier: ^1.0.5 165 + version: 1.0.5 101 166 '@types/react': 102 167 specifier: ^18.3.10 103 - version: 18.3.10 168 + version: 18.3.20 104 169 csstype: 105 - specifier: ^3.1.2 106 - version: 3.1.2 170 + specifier: ^3.1.3 171 + version: 3.1.3 107 172 standalone-electron-types: 108 173 specifier: ^1.0.0 109 174 version: 1.0.0 ··· 114 179 specifier: workspace:* 115 180 version: link:../core 116 181 '@moonlight-mod/lunast': 117 - specifier: ^1.0.0 118 - version: 1.0.0 182 + specifier: catalog:prod 183 + version: 1.0.1 119 184 '@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) 185 + specifier: catalog:prod 186 + version: 1.1.25(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5) 122 187 '@moonlight-mod/moonmap': 123 - specifier: ^1.0.3 124 - version: 1.0.3 188 + specifier: catalog:prod 189 + version: 1.0.5 125 190 '@moonlight-mod/types': 126 191 specifier: workspace:* 127 192 version: link:../types ··· 131 196 '@aashutoshrathi/word-wrap@1.2.6': 132 197 resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} 133 198 engines: {node: '>=0.10.0'} 199 + 200 + '@antfu/ni@24.3.0': 201 + resolution: {integrity: sha512-wBSav4mBxvHEW9RbdSo1SWLQ6MAlT0Dc423weC58yOWqW4OcMvtnNDdDrxOZeJ88fEIyPK93gDUWIelBxzSf8g==} 202 + hasBin: true 134 203 135 204 '@esbuild/android-arm64@0.19.3': 136 205 resolution: {integrity: sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==} ··· 264 333 cpu: [x64] 265 334 os: [win32] 266 335 267 - '@eslint-community/eslint-utils@4.4.0': 268 - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} 336 + '@eslint-community/eslint-utils@4.5.1': 337 + resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} 269 338 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 270 339 peerDependencies: 271 340 eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 272 341 273 - '@eslint-community/regexpp@4.11.1': 274 - resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} 342 + '@eslint-community/regexpp@4.12.1': 343 + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} 275 344 engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 276 345 277 - '@eslint/config-array@0.18.0': 278 - resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} 346 + '@eslint/config-array@0.19.2': 347 + resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} 279 348 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 280 349 281 - '@eslint/core@0.6.0': 282 - resolution: {integrity: sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==} 350 + '@eslint/config-helpers@0.2.1': 351 + resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} 283 352 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 284 353 285 - '@eslint/eslintrc@3.1.0': 286 - resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} 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==} 287 364 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 288 365 289 - '@eslint/js@9.12.0': 290 - resolution: {integrity: sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==} 366 + '@eslint/js@9.23.0': 367 + resolution: {integrity: sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==} 291 368 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 292 369 293 - '@eslint/object-schema@2.1.4': 294 - resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} 370 + '@eslint/object-schema@2.1.6': 371 + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} 295 372 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 296 373 297 - '@eslint/plugin-kit@0.2.0': 298 - resolution: {integrity: sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==} 374 + '@eslint/plugin-kit@0.2.8': 375 + resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} 299 376 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 300 377 301 - '@humanfs/core@0.19.0': 302 - resolution: {integrity: sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==} 378 + '@humanfs/core@0.19.1': 379 + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} 303 380 engines: {node: '>=18.18.0'} 304 381 305 - '@humanfs/node@0.16.5': 306 - resolution: {integrity: sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==} 382 + '@humanfs/node@0.16.6': 383 + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} 307 384 engines: {node: '>=18.18.0'} 308 385 309 386 '@humanwhocodes/module-importer@1.0.1': ··· 314 391 resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} 315 392 engines: {node: '>=18.18'} 316 393 394 + '@humanwhocodes/retry@0.4.2': 395 + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} 396 + engines: {node: '>=18.18'} 397 + 317 398 '@moonlight-mod/eslint-config@https://codeload.github.com/moonlight-mod/eslint-config/tar.gz/e262ac24e1a0955a9b3e0d66da247a0a8c0446c9': 318 399 resolution: {tarball: https://codeload.github.com/moonlight-mod/eslint-config/tar.gz/e262ac24e1a0955a9b3e0d66da247a0a8c0446c9} 319 400 version: 1.0.1 ··· 321 402 eslint: '>= 9' 322 403 typescript: '>= 5.3' 323 404 324 - '@moonlight-mod/lunast@1.0.0': 325 - resolution: {integrity: sha512-kJgf41K12i6/2LbXK97CNO+pNO7ADGh9N4bCQcOPwosocKMcwKHDEZUgPqeihNshY3c3AEW1LiyXjlsl24PdDw==} 405 + '@moonlight-mod/lunast@1.0.1': 406 + resolution: {integrity: sha512-K3vxzDlfFuYKjciIW2FMlcZ1qrrkAGDGpSBlNqYGtJ0sMt9bRCd2lpSpg6AX/giSljDtmAUXa/5mOfUoDQxjBA==} 326 407 327 - '@moonlight-mod/mappings@1.0.10': 328 - resolution: {integrity: sha512-L04To4MhlxOWxvvfVIRwj7d8H5qHthjUfikSx9WMk60qt67+6dFzN9CoAG9uG5l1B27IIEG3voVXBr0oSkooYw==} 408 + '@moonlight-mod/mappings@1.1.25': 409 + resolution: {integrity: sha512-bgnSN9H/IBdMGxGev6RQKXuzhQxwo1090NhIDHnflguZnjiu2pg/usPfh76bqyhxRuX4SS7tiZSNTwBoSflCLg==} 410 + engines: {node: '>=22', npm: pnpm, pnpm: '>=10', yarn: pnpm} 329 411 peerDependencies: 330 - '@moonlight-mod/lunast': ^1.0.0 331 - '@moonlight-mod/moonmap': ^1.0.0 412 + '@moonlight-mod/lunast': ^1.0.1 413 + '@moonlight-mod/moonmap': ^1.0.5 332 414 333 - '@moonlight-mod/moonmap@1.0.3': 334 - resolution: {integrity: sha512-G7pwvrcVDimc388IX6VZFzBXpbuyvqbJ+w9/v+MUIc8P7dADJXQ9YkBWvobtRc6eaBBl1FWUwTeU8oobbxLVag==} 415 + '@moonlight-mod/moonmap@1.0.5': 416 + resolution: {integrity: sha512-Fdpxj8ghdulKB6TlTnchlCPey2YUKgEf1chuO1ofOIcvlqnVPBcQwSf2S80naOUQpXCDo4dQ+LWSE2fmhdDiiw==} 335 417 336 418 '@nodelib/fs.scandir@2.1.5': 337 419 resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} ··· 345 427 resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 346 428 engines: {node: '>= 8'} 347 429 348 - '@pkgr/core@0.1.1': 349 - resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} 430 + '@pkgr/core@0.2.0': 431 + resolution: {integrity: sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==} 350 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==} 351 446 352 447 '@types/estree-jsx@1.0.5': 353 448 resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} ··· 355 450 '@types/estree@1.0.6': 356 451 resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 357 452 453 + '@types/estree@1.0.7': 454 + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} 455 + 358 456 '@types/fbemitter@2.0.35': 359 457 resolution: {integrity: sha512-Xem6d7qUfmouCHntCrRYgDBwbf+WWRd6G+7WEFlEZFZ67LZXiYRvT2LV8wcZa6mIaAil95+ABQdKgB6hPIsnng==} 360 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 + 361 465 '@types/flux@3.1.14': 362 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==} 363 473 364 474 '@types/json-schema@7.0.15': 365 475 resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 366 476 477 + '@types/lodash@4.17.14': 478 + resolution: {integrity: sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==} 479 + 367 480 '@types/node@18.17.17': 368 481 resolution: {integrity: sha512-cOxcXsQ2sxiwkykdJqvyFS+MLQPLvIdwh5l6gNg8qF6s+C7XSkEWOZjK+XhUZd+mYvHV/180g2cnCcIl4l06Pw==} 369 482 370 - '@types/node@20.16.10': 371 - resolution: {integrity: sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==} 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==} 372 491 373 492 '@types/prop-types@15.7.13': 374 493 resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} 375 494 376 - '@types/react@18.3.10': 377 - resolution: {integrity: sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg==} 495 + '@types/react@18.3.20': 496 + resolution: {integrity: sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==} 378 497 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==} 498 + '@typescript-eslint/eslint-plugin@8.29.0': 499 + resolution: {integrity: sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==} 384 500 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 385 501 peerDependencies: 386 502 '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 387 503 eslint: ^8.57.0 || ^9.0.0 388 - typescript: '*' 389 - peerDependenciesMeta: 390 - typescript: 391 - optional: true 504 + typescript: '>=4.8.4 <5.9.0' 392 505 393 - '@typescript-eslint/parser@8.8.1': 394 - resolution: {integrity: sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==} 506 + '@typescript-eslint/parser@8.29.0': 507 + resolution: {integrity: sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==} 395 508 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 396 509 peerDependencies: 397 510 eslint: ^8.57.0 || ^9.0.0 398 - typescript: '*' 399 - peerDependenciesMeta: 400 - typescript: 401 - optional: true 511 + typescript: '>=4.8.4 <5.9.0' 402 512 403 - '@typescript-eslint/scope-manager@8.8.1': 404 - resolution: {integrity: sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==} 513 + '@typescript-eslint/scope-manager@8.29.0': 514 + resolution: {integrity: sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==} 405 515 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 406 516 407 - '@typescript-eslint/type-utils@8.8.1': 408 - resolution: {integrity: sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==} 517 + '@typescript-eslint/type-utils@8.29.0': 518 + resolution: {integrity: sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==} 409 519 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 410 520 peerDependencies: 411 - typescript: '*' 412 - peerDependenciesMeta: 413 - typescript: 414 - optional: true 521 + eslint: ^8.57.0 || ^9.0.0 522 + typescript: '>=4.8.4 <5.9.0' 415 523 416 - '@typescript-eslint/types@8.8.1': 417 - resolution: {integrity: sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==} 524 + '@typescript-eslint/types@8.29.0': 525 + resolution: {integrity: sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==} 418 526 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 419 527 420 - '@typescript-eslint/typescript-estree@8.8.1': 421 - resolution: {integrity: sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==} 528 + '@typescript-eslint/typescript-estree@8.29.0': 529 + resolution: {integrity: sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==} 422 530 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 423 531 peerDependencies: 424 - typescript: '*' 425 - peerDependenciesMeta: 426 - typescript: 427 - optional: true 532 + typescript: '>=4.8.4 <5.9.0' 428 533 429 - '@typescript-eslint/utils@8.8.1': 430 - resolution: {integrity: sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==} 534 + '@typescript-eslint/utils@8.29.0': 535 + resolution: {integrity: sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==} 431 536 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 432 537 peerDependencies: 433 538 eslint: ^8.57.0 || ^9.0.0 539 + typescript: '>=4.8.4 <5.9.0' 434 540 435 - '@typescript-eslint/visitor-keys@8.8.1': 436 - resolution: {integrity: sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==} 541 + '@typescript-eslint/visitor-keys@8.29.0': 542 + resolution: {integrity: sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==} 437 543 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 438 544 439 - '@zenfs/core@1.0.2': 440 - resolution: {integrity: sha512-LMTD4ntn6Ag1y+IeOSVykDDvYC12dsGFtsX8M/54OQrLs7v+YnX4bpo0o2osbm8XFmU2MTNMX/G3PLsvzgWzrg==} 441 - engines: {node: '>= 16'} 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'} 442 551 hasBin: true 443 552 444 - '@zenfs/dom@0.2.16': 445 - resolution: {integrity: sha512-6Ev+ol9hZIgQECNZR+xxjQ/a99EhhrWeiQttm/+U7YJK3HdTjiKfU39DsfGeH64vSqhpa5Vj+LWRx75SHkjw0Q==} 553 + '@zenfs/dom@1.1.6': 554 + resolution: {integrity: sha512-7SBTWgA0esuEv/TE+N/xk6W/XJf8uBF+LhlPNHQdXds0H7aOy/UYsWv/8glvARe+meDMMidoeWFLzUWoMXfjlA==} 446 555 engines: {node: '>= 18'} 447 556 peerDependencies: 448 - '@zenfs/core': ^1.0.0 557 + '@zenfs/core': ^2.0.0 558 + utilium: ^1.9.0 449 559 450 560 abort-controller@3.0.0: 451 561 resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} ··· 456 566 peerDependencies: 457 567 acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 458 568 459 - acorn@8.12.1: 460 - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} 569 + acorn@8.14.1: 570 + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} 461 571 engines: {node: '>=0.4.0'} 462 572 hasBin: true 463 573 ··· 468 578 resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 469 579 engines: {node: '>=8'} 470 580 581 + ansis@3.17.0: 582 + resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==} 583 + engines: {node: '>=14'} 584 + 471 585 argparse@2.0.1: 472 586 resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 473 587 474 - array-buffer-byte-length@1.0.1: 475 - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} 588 + array-buffer-byte-length@1.0.2: 589 + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} 476 590 engines: {node: '>= 0.4'} 477 591 478 592 array-includes@3.1.8: ··· 483 597 resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} 484 598 engines: {node: '>= 0.4'} 485 599 486 - array.prototype.flat@1.3.2: 487 - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} 600 + array.prototype.flat@1.3.3: 601 + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} 488 602 engines: {node: '>= 0.4'} 489 603 490 - array.prototype.flatmap@1.3.2: 491 - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} 604 + array.prototype.flatmap@1.3.3: 605 + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} 492 606 engines: {node: '>= 0.4'} 493 607 494 608 array.prototype.tosorted@1.1.4: 495 609 resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} 496 610 engines: {node: '>= 0.4'} 497 611 498 - arraybuffer.prototype.slice@1.0.3: 499 - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} 612 + arraybuffer.prototype.slice@1.0.4: 613 + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} 500 614 engines: {node: '>= 0.4'} 501 615 502 616 astring@1.9.0: 503 617 resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} 504 618 hasBin: true 619 + 620 + async-function@1.0.0: 621 + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} 622 + engines: {node: '>= 0.4'} 505 623 506 624 available-typed-arrays@1.0.7: 507 625 resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} ··· 526 644 buffer@6.0.3: 527 645 resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} 528 646 529 - call-bind@1.0.7: 530 - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} 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==} 531 661 engines: {node: '>= 0.4'} 532 662 533 663 callsites@3.1.0: ··· 548 678 concat-map@0.0.1: 549 679 resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 550 680 551 - cross-spawn@7.0.3: 552 - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 681 + cross-spawn@7.0.6: 682 + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 553 683 engines: {node: '>= 8'} 554 684 555 - csstype@3.1.2: 556 - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} 557 - 558 685 csstype@3.1.3: 559 686 resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 560 687 561 - data-view-buffer@1.0.1: 562 - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} 688 + data-view-buffer@1.0.2: 689 + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} 563 690 engines: {node: '>= 0.4'} 564 691 565 - data-view-byte-length@1.0.1: 566 - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} 692 + data-view-byte-length@1.0.2: 693 + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} 567 694 engines: {node: '>= 0.4'} 568 695 569 - data-view-byte-offset@1.0.0: 570 - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} 696 + data-view-byte-offset@1.0.1: 697 + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} 571 698 engines: {node: '>= 0.4'} 572 699 573 - debug@4.3.4: 574 - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 700 + debug@4.4.0: 701 + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} 575 702 engines: {node: '>=6.0'} 576 703 peerDependencies: 577 704 supports-color: '*' ··· 590 717 resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} 591 718 engines: {node: '>= 0.4'} 592 719 720 + defu@6.1.4: 721 + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} 722 + 723 + destr@2.0.4: 724 + resolution: {integrity: sha512-FCAorltMy7QwX0QU38jOkhrv20LBpsHA8ogzvMhhPHCCKVCaN6GxrB0GGaWEWBUYI4eEjjfJ95RdP6dk9IdMQA==} 725 + 593 726 doctrine@2.1.0: 594 727 resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} 595 728 engines: {node: '>=0.10.0'} 596 729 597 - es-abstract@1.23.3: 598 - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} 730 + dunder-proto@1.0.1: 731 + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} 599 732 engines: {node: '>= 0.4'} 600 733 601 - es-define-property@1.0.0: 602 - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} 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==} 603 740 engines: {node: '>= 0.4'} 604 741 605 742 es-errors@1.3.0: 606 743 resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} 607 744 engines: {node: '>= 0.4'} 608 745 609 - es-iterator-helpers@1.1.0: 610 - resolution: {integrity: sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==} 746 + es-iterator-helpers@1.2.1: 747 + resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} 611 748 engines: {node: '>= 0.4'} 612 749 613 - es-object-atoms@1.0.0: 614 - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} 750 + es-object-atoms@1.1.1: 751 + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} 615 752 engines: {node: '>= 0.4'} 616 753 617 - es-set-tostringtag@2.0.3: 618 - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} 754 + es-set-tostringtag@2.1.0: 755 + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} 619 756 engines: {node: '>= 0.4'} 620 757 621 - es-shim-unscopables@1.0.2: 622 - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} 758 + es-shim-unscopables@1.1.0: 759 + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} 760 + engines: {node: '>= 0.4'} 623 761 624 - es-to-primitive@1.2.1: 625 - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} 762 + es-to-primitive@1.3.0: 763 + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} 626 764 engines: {node: '>= 0.4'} 627 765 628 766 esbuild-copy-static-files@0.1.0: ··· 643 781 peerDependencies: 644 782 eslint: '>=7.0.0' 645 783 646 - eslint-plugin-prettier@5.2.1: 647 - resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} 784 + eslint-plugin-prettier@5.2.6: 785 + resolution: {integrity: sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==} 648 786 engines: {node: ^14.18.0 || >=16.0.0} 649 787 peerDependencies: 650 788 '@types/eslint': '>=8.0.0' 651 789 eslint: '>=8.0.0' 652 - eslint-config-prettier: '*' 790 + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' 653 791 prettier: '>=3.0.0' 654 792 peerDependenciesMeta: 655 793 '@types/eslint': ··· 657 795 eslint-config-prettier: 658 796 optional: true 659 797 660 - eslint-plugin-react@7.37.1: 661 - resolution: {integrity: sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==} 798 + eslint-plugin-react@7.37.5: 799 + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} 662 800 engines: {node: '>=4'} 663 801 peerDependencies: 664 802 eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 665 803 666 - eslint-scope@8.1.0: 667 - resolution: {integrity: sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==} 804 + eslint-scope@8.3.0: 805 + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} 668 806 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 669 807 670 808 eslint-visitor-keys@3.4.3: 671 809 resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 672 810 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 673 811 674 - eslint-visitor-keys@4.1.0: 675 - resolution: {integrity: sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==} 812 + eslint-visitor-keys@4.2.0: 813 + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} 676 814 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 677 815 678 - eslint@9.12.0: 679 - resolution: {integrity: sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==} 816 + eslint@9.23.0: 817 + resolution: {integrity: sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==} 680 818 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 681 819 hasBin: true 682 820 peerDependencies: ··· 685 823 jiti: 686 824 optional: true 687 825 688 - espree@10.2.0: 689 - resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} 826 + espree@10.3.0: 827 + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} 690 828 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 691 829 692 - esquery@1.5.0: 693 - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} 830 + esquery@1.6.0: 831 + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} 694 832 engines: {node: '>=0.10'} 695 833 696 834 esrecurse@4.3.0: ··· 738 876 fastq@1.17.1: 739 877 resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} 740 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 + 741 887 file-entry-cache@8.0.0: 742 888 resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} 743 889 engines: {node: '>=16.0.0'} ··· 746 892 resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 747 893 engines: {node: '>=8'} 748 894 895 + find-up-simple@1.0.1: 896 + resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} 897 + engines: {node: '>=18'} 898 + 749 899 find-up@5.0.0: 750 900 resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 751 901 engines: {node: '>=10'} ··· 757 907 flatted@3.2.9: 758 908 resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} 759 909 760 - for-each@0.3.3: 761 - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} 910 + for-each@0.3.5: 911 + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} 912 + engines: {node: '>= 0.4'} 762 913 763 914 function-bind@1.1.2: 764 915 resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 765 916 766 - function.prototype.name@1.1.6: 767 - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} 917 + function.prototype.name@1.1.8: 918 + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} 768 919 engines: {node: '>= 0.4'} 769 920 770 921 functions-have-names@1.2.3: 771 922 resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} 772 923 773 - get-intrinsic@1.2.4: 774 - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} 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==} 775 929 engines: {node: '>= 0.4'} 776 930 777 - get-symbol-description@1.0.2: 778 - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} 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==} 779 937 engines: {node: '>= 0.4'} 780 938 781 939 glob-parent@5.1.2: ··· 794 952 resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} 795 953 engines: {node: '>= 0.4'} 796 954 797 - gopd@1.0.1: 798 - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} 955 + gopd@1.2.0: 956 + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} 957 + engines: {node: '>= 0.4'} 799 958 800 959 graphemer@1.4.0: 801 960 resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 802 961 803 - has-bigints@1.0.2: 804 - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} 962 + has-bigints@1.1.0: 963 + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} 964 + engines: {node: '>= 0.4'} 805 965 806 966 has-flag@4.0.0: 807 967 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} ··· 810 970 has-property-descriptors@1.0.2: 811 971 resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} 812 972 813 - has-proto@1.0.3: 814 - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} 973 + has-proto@1.2.0: 974 + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} 815 975 engines: {node: '>= 0.4'} 816 976 817 - has-symbols@1.0.3: 818 - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} 977 + has-symbols@1.1.0: 978 + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} 819 979 engines: {node: '>= 0.4'} 820 980 821 981 has-tostringtag@1.0.2: ··· 834 994 ieee754@1.2.1: 835 995 resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 836 996 837 - ignore@5.3.0: 838 - resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} 839 - engines: {node: '>= 4'} 840 - 841 997 ignore@5.3.2: 842 998 resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 843 999 engines: {node: '>= 4'} ··· 850 1006 resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 851 1007 engines: {node: '>=0.8.19'} 852 1008 853 - internal-slot@1.0.7: 854 - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} 1009 + internal-slot@1.1.0: 1010 + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} 855 1011 engines: {node: '>= 0.4'} 856 1012 857 - is-array-buffer@3.0.4: 858 - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} 1013 + is-array-buffer@3.0.5: 1014 + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} 859 1015 engines: {node: '>= 0.4'} 860 1016 861 - is-async-function@2.0.0: 862 - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} 1017 + is-async-function@2.1.1: 1018 + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} 863 1019 engines: {node: '>= 0.4'} 864 1020 865 - is-bigint@1.0.4: 866 - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} 1021 + is-bigint@1.1.0: 1022 + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} 1023 + engines: {node: '>= 0.4'} 867 1024 868 - is-boolean-object@1.1.2: 869 - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} 1025 + is-boolean-object@1.2.2: 1026 + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} 870 1027 engines: {node: '>= 0.4'} 871 1028 872 1029 is-callable@1.2.7: 873 1030 resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} 874 1031 engines: {node: '>= 0.4'} 875 1032 876 - is-core-module@2.15.1: 877 - resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} 1033 + is-core-module@2.16.1: 1034 + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} 878 1035 engines: {node: '>= 0.4'} 879 1036 880 - is-data-view@1.0.1: 881 - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} 1037 + is-data-view@1.0.2: 1038 + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} 882 1039 engines: {node: '>= 0.4'} 883 1040 884 - is-date-object@1.0.5: 885 - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} 1041 + is-date-object@1.1.0: 1042 + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} 886 1043 engines: {node: '>= 0.4'} 887 1044 888 1045 is-extglob@2.1.1: 889 1046 resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 890 1047 engines: {node: '>=0.10.0'} 891 1048 892 - is-finalizationregistry@1.0.2: 893 - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} 1049 + is-finalizationregistry@1.1.1: 1050 + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} 1051 + engines: {node: '>= 0.4'} 894 1052 895 - is-generator-function@1.0.10: 896 - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} 1053 + is-generator-function@1.1.0: 1054 + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} 897 1055 engines: {node: '>= 0.4'} 898 1056 899 1057 is-glob@4.0.3: ··· 904 1062 resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} 905 1063 engines: {node: '>= 0.4'} 906 1064 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==} 1065 + is-number-object@1.1.1: 1066 + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} 913 1067 engines: {node: '>= 0.4'} 914 1068 915 1069 is-number@7.0.0: 916 1070 resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 917 1071 engines: {node: '>=0.12.0'} 918 1072 919 - is-regex@1.1.4: 920 - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} 1073 + is-regex@1.2.1: 1074 + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} 921 1075 engines: {node: '>= 0.4'} 922 1076 923 1077 is-set@2.0.3: 924 1078 resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} 925 1079 engines: {node: '>= 0.4'} 926 1080 927 - is-shared-array-buffer@1.0.3: 928 - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} 1081 + is-shared-array-buffer@1.0.4: 1082 + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} 929 1083 engines: {node: '>= 0.4'} 930 1084 931 - is-string@1.0.7: 932 - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} 1085 + is-string@1.1.1: 1086 + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} 933 1087 engines: {node: '>= 0.4'} 934 1088 935 - is-symbol@1.0.4: 936 - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} 1089 + is-symbol@1.1.1: 1090 + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} 937 1091 engines: {node: '>= 0.4'} 938 1092 939 - is-typed-array@1.1.13: 940 - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} 1093 + is-typed-array@1.1.15: 1094 + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} 941 1095 engines: {node: '>= 0.4'} 942 1096 943 1097 is-weakmap@2.0.2: 944 1098 resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} 945 1099 engines: {node: '>= 0.4'} 946 1100 947 - is-weakref@1.0.2: 948 - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} 1101 + is-weakref@1.1.1: 1102 + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} 1103 + engines: {node: '>= 0.4'} 949 1104 950 - is-weakset@2.0.3: 951 - resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} 1105 + is-weakset@2.0.4: 1106 + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} 952 1107 engines: {node: '>= 0.4'} 953 1108 954 1109 isarray@2.0.5: ··· 957 1112 isexe@2.0.0: 958 1113 resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 959 1114 960 - iterator.prototype@1.1.3: 961 - resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==} 1115 + iterator.prototype@1.1.5: 1116 + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} 962 1117 engines: {node: '>= 0.4'} 963 1118 1119 + jiti@2.4.2: 1120 + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} 1121 + hasBin: true 1122 + 964 1123 js-tokens@4.0.0: 965 1124 resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 966 1125 ··· 999 1158 resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 1000 1159 hasBin: true 1001 1160 1161 + math-intrinsics@1.1.0: 1162 + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} 1163 + engines: {node: '>= 0.4'} 1164 + 1002 1165 merge2@1.4.1: 1003 1166 resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1004 1167 engines: {node: '>= 8'} ··· 1014 1177 resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1015 1178 engines: {node: '>=8.6'} 1016 1179 1180 + mimic-function@5.0.1: 1181 + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} 1182 + engines: {node: '>=18'} 1183 + 1017 1184 minimatch@3.1.2: 1018 1185 resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1019 1186 ··· 1021 1188 resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1022 1189 engines: {node: '>=16 || 14 >=14.17'} 1023 1190 1024 - ms@2.1.2: 1025 - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 1191 + ms@2.1.3: 1192 + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1026 1193 1027 1194 nanotar@0.1.1: 1028 1195 resolution: {integrity: sha512-AiJsGsSF3O0havL1BydvI4+wR76sKT+okKRwWIaK96cZUnXqH0uNBOsHlbwZq3+m2BR1VKqHDVudl3gO4mYjpQ==} ··· 1030 1197 natural-compare@1.4.0: 1031 1198 resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1032 1199 1200 + node-fetch-native@1.6.6: 1201 + resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} 1202 + 1033 1203 object-assign@4.1.1: 1034 1204 resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1035 1205 engines: {node: '>=0.10.0'} 1036 1206 1037 - object-inspect@1.13.2: 1038 - resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} 1207 + object-inspect@1.13.4: 1208 + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} 1039 1209 engines: {node: '>= 0.4'} 1040 1210 1041 1211 object-keys@1.1.1: 1042 1212 resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} 1043 1213 engines: {node: '>= 0.4'} 1044 1214 1045 - object.assign@4.1.5: 1046 - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} 1215 + object.assign@4.1.7: 1216 + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} 1047 1217 engines: {node: '>= 0.4'} 1048 1218 1049 - object.entries@1.1.8: 1050 - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} 1219 + object.entries@1.1.9: 1220 + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} 1051 1221 engines: {node: '>= 0.4'} 1052 1222 1053 1223 object.fromentries@2.0.8: 1054 1224 resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} 1055 1225 engines: {node: '>= 0.4'} 1056 1226 1057 - object.values@1.2.0: 1058 - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} 1227 + object.values@1.2.1: 1228 + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} 1059 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'} 1060 1237 1061 1238 optionator@0.9.3: 1062 1239 resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} 1063 1240 engines: {node: '>= 0.8.0'} 1064 1241 1242 + own-keys@1.0.1: 1243 + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} 1244 + engines: {node: '>= 0.4'} 1245 + 1065 1246 p-limit@3.1.0: 1066 1247 resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1067 1248 engines: {node: '>=10'} ··· 1069 1250 p-locate@5.0.0: 1070 1251 resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1071 1252 engines: {node: '>=10'} 1253 + 1254 + package-manager-detector@1.1.0: 1255 + resolution: {integrity: sha512-Y8f9qUlBzW8qauJjd/eu6jlpJZsuPJm2ZAV0cDVd420o4EdpH5RPdoCv+60/TdJflGatr4sDfpAL6ArWZbM5tA==} 1072 1256 1073 1257 parent-module@1.0.1: 1074 1258 resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} ··· 1085 1269 path-parse@1.0.7: 1086 1270 resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1087 1271 1272 + pathe@2.0.3: 1273 + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} 1274 + 1088 1275 picomatch@2.3.1: 1089 1276 resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1090 1277 engines: {node: '>=8.6'} 1091 1278 1092 - possible-typed-array-names@1.0.0: 1093 - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} 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==} 1094 1288 engines: {node: '>= 0.4'} 1095 1289 1096 1290 prelude-ls@1.2.1: ··· 1117 1311 resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1118 1312 engines: {node: '>=6'} 1119 1313 1314 + quansync@0.2.10: 1315 + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} 1316 + 1120 1317 queue-microtask@1.2.3: 1121 1318 resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1122 1319 ··· 1127 1324 resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} 1128 1325 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1129 1326 1130 - reflect.getprototypeof@1.0.6: 1131 - resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} 1327 + reflect.getprototypeof@1.0.10: 1328 + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} 1132 1329 engines: {node: '>= 0.4'} 1133 1330 1134 - regexp.prototype.flags@1.5.3: 1135 - resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} 1331 + regexp.prototype.flags@1.5.4: 1332 + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} 1136 1333 engines: {node: '>= 0.4'} 1137 1334 1138 1335 resolve-from@4.0.0: ··· 1143 1340 resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} 1144 1341 hasBin: true 1145 1342 1343 + restore-cursor@5.1.0: 1344 + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} 1345 + engines: {node: '>=18'} 1346 + 1146 1347 reusify@1.0.4: 1147 1348 resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1148 1349 engines: {iojs: '>=1.0.0', node: '>=0.10.0'} ··· 1150 1351 run-parallel@1.2.0: 1151 1352 resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1152 1353 1153 - safe-array-concat@1.1.2: 1154 - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} 1354 + safe-array-concat@1.1.3: 1355 + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} 1155 1356 engines: {node: '>=0.4'} 1156 1357 1157 - safe-buffer@5.1.2: 1158 - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} 1159 - 1160 1358 safe-buffer@5.2.1: 1161 1359 resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1162 1360 1163 - safe-regex-test@1.0.3: 1164 - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} 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==} 1165 1367 engines: {node: '>= 0.4'} 1166 1368 1167 1369 semver@6.3.1: 1168 1370 resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 1169 1371 hasBin: true 1170 1372 1171 - semver@7.6.3: 1172 - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} 1373 + semver@7.7.1: 1374 + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} 1173 1375 engines: {node: '>=10'} 1174 1376 hasBin: true 1175 1377 ··· 1181 1383 resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} 1182 1384 engines: {node: '>= 0.4'} 1183 1385 1386 + set-proto@1.0.0: 1387 + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} 1388 + engines: {node: '>= 0.4'} 1389 + 1184 1390 shebang-command@2.0.0: 1185 1391 resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1186 1392 engines: {node: '>=8'} ··· 1189 1395 resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1190 1396 engines: {node: '>=8'} 1191 1397 1192 - side-channel@1.0.6: 1193 - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} 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==} 1194 1408 engines: {node: '>= 0.4'} 1195 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 + 1196 1418 standalone-electron-types@1.0.0: 1197 1419 resolution: {integrity: sha512-0HOi/tlTz3mjWhsAz4uRbpQcHMZ+ifj1JzWW9nugykOHClBBG77ps8QinrzX1eow4Iw2pnC+RFaSYRgufF4BOg==} 1198 1420 1199 - string.prototype.matchall@4.0.11: 1200 - resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} 1421 + string.prototype.matchall@4.0.12: 1422 + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} 1201 1423 engines: {node: '>= 0.4'} 1202 1424 1203 1425 string.prototype.repeat@1.0.0: 1204 1426 resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} 1205 1427 1206 - string.prototype.trim@1.2.9: 1207 - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} 1428 + string.prototype.trim@1.2.10: 1429 + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} 1208 1430 engines: {node: '>= 0.4'} 1209 1431 1210 - string.prototype.trimend@1.0.8: 1211 - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} 1432 + string.prototype.trimend@1.0.9: 1433 + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} 1434 + engines: {node: '>= 0.4'} 1212 1435 1213 1436 string.prototype.trimstart@1.0.8: 1214 1437 resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} ··· 1229 1452 resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1230 1453 engines: {node: '>= 0.4'} 1231 1454 1232 - synckit@0.9.2: 1233 - resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} 1455 + synckit@0.11.1: 1456 + resolution: {integrity: sha512-fWZqNBZNNFp/7mTUy1fSsydhKsAKJ+u90Nk7kOK5Gcq9vObaqLBLjWFDBkyVU9Vvc6Y71VbOevMuGhqv02bT+Q==} 1234 1457 engines: {node: ^14.18.0 || >=16.0.0} 1235 1458 1236 - text-table@0.2.0: 1237 - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 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'} 1238 1469 1239 1470 to-regex-range@5.0.1: 1240 1471 resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1241 1472 engines: {node: '>=8.0'} 1242 1473 1243 - ts-api-utils@1.3.0: 1244 - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} 1245 - engines: {node: '>=16'} 1474 + ts-api-utils@2.1.0: 1475 + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} 1476 + engines: {node: '>=18.12'} 1246 1477 peerDependencies: 1247 - typescript: '>=4.2.0' 1478 + typescript: '>=4.8.4' 1248 1479 1249 - tslib@2.7.0: 1250 - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} 1480 + tslib@2.8.1: 1481 + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 1251 1482 1252 1483 type-check@0.4.0: 1253 1484 resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1254 1485 engines: {node: '>= 0.8.0'} 1255 1486 1256 - typed-array-buffer@1.0.2: 1257 - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} 1487 + typed-array-buffer@1.0.3: 1488 + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} 1258 1489 engines: {node: '>= 0.4'} 1259 1490 1260 - typed-array-byte-length@1.0.1: 1261 - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} 1491 + typed-array-byte-length@1.0.3: 1492 + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} 1262 1493 engines: {node: '>= 0.4'} 1263 1494 1264 - typed-array-byte-offset@1.0.2: 1265 - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} 1495 + typed-array-byte-offset@1.0.4: 1496 + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} 1266 1497 engines: {node: '>= 0.4'} 1267 1498 1268 - typed-array-length@1.0.6: 1269 - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} 1499 + typed-array-length@1.0.7: 1500 + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} 1270 1501 engines: {node: '>= 0.4'} 1271 1502 1272 - typescript-eslint@8.8.1: 1273 - resolution: {integrity: sha512-R0dsXFt6t4SAFjUSKFjMh4pXDtq04SsFKCVGDP3ZOzNP7itF0jBcZYU4fMsZr4y7O7V7Nc751dDeESbe4PbQMQ==} 1503 + typescript-eslint@8.29.0: 1504 + resolution: {integrity: sha512-ep9rVd9B4kQsZ7ZnWCVxUE/xDLUUUsRzE0poAeNu+4CkFErLfuvPt/qtm2EpnSyfvsR0S6QzDFSrPCFBwf64fg==} 1274 1505 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 1275 1506 peerDependencies: 1276 - typescript: '*' 1277 - peerDependenciesMeta: 1278 - typescript: 1279 - optional: true 1507 + eslint: ^8.57.0 || ^9.0.0 1508 + typescript: '>=4.8.4 <5.9.0' 1280 1509 1281 - typescript@5.3.2: 1282 - resolution: {integrity: sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==} 1510 + typescript@5.8.2: 1511 + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} 1283 1512 engines: {node: '>=14.17'} 1284 1513 hasBin: true 1285 1514 1286 - unbox-primitive@1.0.2: 1287 - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} 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==} 1288 1527 1289 - undici-types@6.19.8: 1290 - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} 1528 + undici-types@6.21.0: 1529 + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} 1291 1530 1292 1531 uri-js@4.4.1: 1293 1532 resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1294 1533 1295 - utilium@0.7.1: 1296 - resolution: {integrity: sha512-2ocvTkI7U8LERmwxL0LhFUvEfN66UqcjF6tMiURvUwSyU7U1QC9gST+3iSUSiGccFfnP3f2EXwHNXOnOzx+lAg==} 1534 + utilium@1.10.1: 1535 + resolution: {integrity: sha512-GQINDTb/ocyz4acQj3GXAe0wipYxws6L+9ouqaq10KlInTk9DGvW9TJd0pYa/Xu3cppNnZuB4T/sBuSXpcN2ng==} 1297 1536 1298 - which-boxed-primitive@1.0.2: 1299 - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} 1537 + which-boxed-primitive@1.1.1: 1538 + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} 1539 + engines: {node: '>= 0.4'} 1300 1540 1301 - which-builtin-type@1.1.4: 1302 - resolution: {integrity: sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==} 1541 + which-builtin-type@1.2.1: 1542 + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} 1303 1543 engines: {node: '>= 0.4'} 1304 1544 1305 1545 which-collection@1.0.2: 1306 1546 resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} 1307 1547 engines: {node: '>= 0.4'} 1308 1548 1309 - which-typed-array@1.1.15: 1310 - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} 1549 + which-typed-array@1.1.19: 1550 + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} 1311 1551 engines: {node: '>= 0.4'} 1312 1552 1313 1553 which@2.0.2: ··· 1315 1555 engines: {node: '>= 8'} 1316 1556 hasBin: true 1317 1557 1558 + yaml@2.7.1: 1559 + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} 1560 + engines: {node: '>= 14'} 1561 + hasBin: true 1562 + 1318 1563 yocto-queue@0.1.0: 1319 1564 resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1320 1565 engines: {node: '>=10'} 1321 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 + 1322 1585 snapshots: 1323 1586 1324 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 1325 1595 1326 1596 '@esbuild/android-arm64@0.19.3': 1327 1597 optional: true ··· 1389 1659 '@esbuild/win32-x64@0.19.3': 1390 1660 optional: true 1391 1661 1392 - '@eslint-community/eslint-utils@4.4.0(eslint@9.12.0)': 1662 + '@eslint-community/eslint-utils@4.5.1(eslint@9.23.0(jiti@2.4.2))': 1393 1663 dependencies: 1394 - eslint: 9.12.0 1664 + eslint: 9.23.0(jiti@2.4.2) 1395 1665 eslint-visitor-keys: 3.4.3 1396 1666 1397 - '@eslint-community/regexpp@4.11.1': {} 1667 + '@eslint-community/regexpp@4.12.1': {} 1398 1668 1399 - '@eslint/config-array@0.18.0': 1669 + '@eslint/config-array@0.19.2': 1400 1670 dependencies: 1401 - '@eslint/object-schema': 2.1.4 1402 - debug: 4.3.4 1671 + '@eslint/object-schema': 2.1.6 1672 + debug: 4.4.0 1403 1673 minimatch: 3.1.2 1404 1674 transitivePeerDependencies: 1405 1675 - supports-color 1406 1676 1407 - '@eslint/core@0.6.0': {} 1677 + '@eslint/config-helpers@0.2.1': {} 1408 1678 1409 - '@eslint/eslintrc@3.1.0': 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': 1410 1688 dependencies: 1411 1689 ajv: 6.12.6 1412 - debug: 4.3.4 1413 - espree: 10.2.0 1690 + debug: 4.4.0 1691 + espree: 10.3.0 1414 1692 globals: 14.0.0 1415 - ignore: 5.3.0 1693 + ignore: 5.3.2 1416 1694 import-fresh: 3.3.0 1417 1695 js-yaml: 4.1.0 1418 1696 minimatch: 3.1.2 ··· 1420 1698 transitivePeerDependencies: 1421 1699 - supports-color 1422 1700 1423 - '@eslint/js@9.12.0': {} 1701 + '@eslint/js@9.23.0': {} 1424 1702 1425 - '@eslint/object-schema@2.1.4': {} 1703 + '@eslint/object-schema@2.1.6': {} 1426 1704 1427 - '@eslint/plugin-kit@0.2.0': 1705 + '@eslint/plugin-kit@0.2.8': 1428 1706 dependencies: 1707 + '@eslint/core': 0.13.0 1429 1708 levn: 0.4.1 1430 1709 1431 - '@humanfs/core@0.19.0': {} 1710 + '@humanfs/core@0.19.1': {} 1432 1711 1433 - '@humanfs/node@0.16.5': 1712 + '@humanfs/node@0.16.6': 1434 1713 dependencies: 1435 - '@humanfs/core': 0.19.0 1714 + '@humanfs/core': 0.19.1 1436 1715 '@humanwhocodes/retry': 0.3.1 1437 1716 1438 1717 '@humanwhocodes/module-importer@1.0.1': {} 1439 1718 1440 1719 '@humanwhocodes/retry@0.3.1': {} 1441 1720 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)': 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)': 1443 1724 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) 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) 1451 1732 transitivePeerDependencies: 1452 1733 - '@types/eslint' 1453 1734 - prettier 1454 1735 - supports-color 1455 1736 1456 - '@moonlight-mod/lunast@1.0.0': 1737 + '@moonlight-mod/lunast@1.0.1': 1457 1738 dependencies: 1458 1739 astring: 1.9.0 1459 1740 estree-toolkit: 1.7.8 1460 1741 meriyah: 6.0.1 1461 1742 1462 - '@moonlight-mod/mappings@1.0.10(@moonlight-mod/lunast@1.0.0)(@moonlight-mod/moonmap@1.0.3)': 1743 + '@moonlight-mod/mappings@1.1.25(@moonlight-mod/lunast@1.0.1)(@moonlight-mod/moonmap@1.0.5)': 1463 1744 dependencies: 1464 - '@moonlight-mod/lunast': 1.0.0 1465 - '@moonlight-mod/moonmap': 1.0.3 1745 + '@moonlight-mod/lunast': 1.0.1 1746 + '@moonlight-mod/moonmap': 1.0.5 1747 + '@types/chroma-js': 3.1.0 1466 1748 '@types/flux': 3.1.14 1467 - '@types/react': 18.3.10 1749 + '@types/highlightjs': 9.12.6 1750 + '@types/lodash': 4.17.14 1751 + '@types/platform': 1.3.6 1752 + '@types/react': 18.3.20 1468 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 1469 1759 1470 - '@moonlight-mod/moonmap@1.0.3': {} 1760 + '@moonlight-mod/moonmap@1.0.5': {} 1471 1761 1472 1762 '@nodelib/fs.scandir@2.1.5': 1473 1763 dependencies: ··· 1481 1771 '@nodelib/fs.scandir': 2.1.5 1482 1772 fastq: 1.17.1 1483 1773 1484 - '@pkgr/core@0.1.1': {} 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 1485 1792 1486 1793 '@types/estree-jsx@1.0.5': 1487 1794 dependencies: 1488 1795 '@types/estree': 1.0.6 1489 1796 1490 1797 '@types/estree@1.0.6': {} 1798 + 1799 + '@types/estree@1.0.7': 1800 + optional: true 1491 1801 1492 1802 '@types/fbemitter@2.0.35': {} 1493 1803 1804 + '@types/filesystem@0.0.36': 1805 + dependencies: 1806 + '@types/filewriter': 0.0.33 1807 + 1808 + '@types/filewriter@0.0.33': {} 1809 + 1494 1810 '@types/flux@3.1.14': 1495 1811 dependencies: 1496 1812 '@types/fbemitter': 2.0.35 1497 - '@types/react': 18.3.10 1813 + '@types/react': 18.3.20 1814 + 1815 + '@types/har-format@1.2.16': {} 1816 + 1817 + '@types/highlightjs@9.12.6': {} 1498 1818 1499 1819 '@types/json-schema@7.0.15': {} 1500 1820 1821 + '@types/lodash@4.17.14': {} 1822 + 1501 1823 '@types/node@18.17.17': {} 1502 1824 1503 - '@types/node@20.16.10': 1825 + '@types/node@22.13.6': 1826 + dependencies: 1827 + undici-types: 6.20.0 1828 + 1829 + '@types/node@22.14.0': 1504 1830 dependencies: 1505 - undici-types: 6.19.8 1831 + undici-types: 6.21.0 1832 + 1833 + '@types/platform@1.3.6': {} 1506 1834 1507 1835 '@types/prop-types@15.7.13': {} 1508 1836 1509 - '@types/react@18.3.10': 1837 + '@types/react@18.3.20': 1510 1838 dependencies: 1511 1839 '@types/prop-types': 15.7.13 1512 1840 csstype: 3.1.3 1513 1841 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)': 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)': 1520 1843 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 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) 1528 1851 graphemer: 1.4.0 1529 1852 ignore: 5.3.2 1530 1853 natural-compare: 1.4.0 1531 - ts-api-utils: 1.3.0(typescript@5.3.2) 1532 - optionalDependencies: 1533 - typescript: 5.3.2 1854 + ts-api-utils: 2.1.0(typescript@5.8.2) 1855 + typescript: 5.8.2 1534 1856 transitivePeerDependencies: 1535 1857 - supports-color 1536 1858 1537 - '@typescript-eslint/parser@8.8.1(eslint@9.12.0)(typescript@5.3.2)': 1859 + '@typescript-eslint/parser@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)': 1538 1860 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 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 1547 1868 transitivePeerDependencies: 1548 1869 - supports-color 1549 1870 1550 - '@typescript-eslint/scope-manager@8.8.1': 1871 + '@typescript-eslint/scope-manager@8.29.0': 1551 1872 dependencies: 1552 - '@typescript-eslint/types': 8.8.1 1553 - '@typescript-eslint/visitor-keys': 8.8.1 1873 + '@typescript-eslint/types': 8.29.0 1874 + '@typescript-eslint/visitor-keys': 8.29.0 1554 1875 1555 - '@typescript-eslint/type-utils@8.8.1(eslint@9.12.0)(typescript@5.3.2)': 1876 + '@typescript-eslint/type-utils@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)': 1556 1877 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 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 1563 1884 transitivePeerDependencies: 1564 - - eslint 1565 1885 - supports-color 1566 1886 1567 - '@typescript-eslint/types@8.8.1': {} 1887 + '@typescript-eslint/types@8.29.0': {} 1568 1888 1569 - '@typescript-eslint/typescript-estree@8.8.1(typescript@5.3.2)': 1889 + '@typescript-eslint/typescript-estree@8.29.0(typescript@5.8.2)': 1570 1890 dependencies: 1571 - '@typescript-eslint/types': 8.8.1 1572 - '@typescript-eslint/visitor-keys': 8.8.1 1573 - debug: 4.3.4 1891 + '@typescript-eslint/types': 8.29.0 1892 + '@typescript-eslint/visitor-keys': 8.29.0 1893 + debug: 4.4.0 1574 1894 fast-glob: 3.3.2 1575 1895 is-glob: 4.0.3 1576 1896 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 1897 + semver: 7.7.1 1898 + ts-api-utils: 2.1.0(typescript@5.8.2) 1899 + typescript: 5.8.2 1581 1900 transitivePeerDependencies: 1582 1901 - supports-color 1583 1902 1584 - '@typescript-eslint/utils@8.8.1(eslint@9.12.0)(typescript@5.3.2)': 1903 + '@typescript-eslint/utils@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)': 1585 1904 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 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 1591 1911 transitivePeerDependencies: 1592 1912 - supports-color 1593 - - typescript 1594 1913 1595 - '@typescript-eslint/visitor-keys@8.8.1': 1914 + '@typescript-eslint/visitor-keys@8.29.0': 1596 1915 dependencies: 1597 - '@typescript-eslint/types': 8.8.1 1598 - eslint-visitor-keys: 3.4.3 1916 + '@typescript-eslint/types': 8.29.0 1917 + eslint-visitor-keys: 4.2.0 1599 1918 1600 - '@zenfs/core@1.0.2': 1919 + '@xterm/xterm@5.5.0': 1920 + optional: true 1921 + 1922 + '@zenfs/core@2.0.0': 1601 1923 dependencies: 1602 - '@types/node': 20.16.10 1603 - '@types/readable-stream': 4.0.15 1924 + '@types/node': 22.13.6 1604 1925 buffer: 6.0.3 1605 1926 eventemitter3: 5.0.1 1606 - minimatch: 9.0.5 1607 1927 readable-stream: 4.5.2 1608 - utilium: 0.7.1 1928 + utilium: 1.10.1 1609 1929 1610 - '@zenfs/dom@0.2.16(@zenfs/core@1.0.2)': 1930 + '@zenfs/dom@1.1.6(@zenfs/core@2.0.0)(utilium@1.10.1)': 1611 1931 dependencies: 1612 - '@zenfs/core': 1.0.2 1932 + '@zenfs/core': 2.0.0 1933 + utilium: 1.10.1 1613 1934 1614 1935 abort-controller@3.0.0: 1615 1936 dependencies: 1616 1937 event-target-shim: 5.0.1 1617 1938 1618 - acorn-jsx@5.3.2(acorn@8.12.1): 1939 + acorn-jsx@5.3.2(acorn@8.14.1): 1619 1940 dependencies: 1620 - acorn: 8.12.1 1941 + acorn: 8.14.1 1621 1942 1622 - acorn@8.12.1: {} 1943 + acorn@8.14.1: {} 1623 1944 1624 1945 ajv@6.12.6: 1625 1946 dependencies: ··· 1632 1953 dependencies: 1633 1954 color-convert: 2.0.1 1634 1955 1956 + ansis@3.17.0: {} 1957 + 1635 1958 argparse@2.0.1: {} 1636 1959 1637 - array-buffer-byte-length@1.0.1: 1960 + array-buffer-byte-length@1.0.2: 1638 1961 dependencies: 1639 - call-bind: 1.0.7 1640 - is-array-buffer: 3.0.4 1962 + call-bound: 1.0.4 1963 + is-array-buffer: 3.0.5 1641 1964 1642 1965 array-includes@3.1.8: 1643 1966 dependencies: 1644 - call-bind: 1.0.7 1967 + call-bind: 1.0.8 1645 1968 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 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 1650 1973 1651 1974 array.prototype.findlast@1.2.5: 1652 1975 dependencies: 1653 - call-bind: 1.0.7 1976 + call-bind: 1.0.8 1654 1977 define-properties: 1.2.1 1655 - es-abstract: 1.23.3 1978 + es-abstract: 1.23.9 1656 1979 es-errors: 1.3.0 1657 - es-object-atoms: 1.0.0 1658 - es-shim-unscopables: 1.0.2 1980 + es-object-atoms: 1.1.1 1981 + es-shim-unscopables: 1.1.0 1659 1982 1660 - array.prototype.flat@1.3.2: 1983 + array.prototype.flat@1.3.3: 1661 1984 dependencies: 1662 - call-bind: 1.0.7 1985 + call-bind: 1.0.8 1663 1986 define-properties: 1.2.1 1664 - es-abstract: 1.23.3 1665 - es-shim-unscopables: 1.0.2 1987 + es-abstract: 1.23.9 1988 + es-shim-unscopables: 1.1.0 1666 1989 1667 - array.prototype.flatmap@1.3.2: 1990 + array.prototype.flatmap@1.3.3: 1668 1991 dependencies: 1669 - call-bind: 1.0.7 1992 + call-bind: 1.0.8 1670 1993 define-properties: 1.2.1 1671 - es-abstract: 1.23.3 1672 - es-shim-unscopables: 1.0.2 1994 + es-abstract: 1.23.9 1995 + es-shim-unscopables: 1.1.0 1673 1996 1674 1997 array.prototype.tosorted@1.1.4: 1675 1998 dependencies: 1676 - call-bind: 1.0.7 1999 + call-bind: 1.0.8 1677 2000 define-properties: 1.2.1 1678 - es-abstract: 1.23.3 2001 + es-abstract: 1.23.9 1679 2002 es-errors: 1.3.0 1680 - es-shim-unscopables: 1.0.2 2003 + es-shim-unscopables: 1.1.0 1681 2004 1682 - arraybuffer.prototype.slice@1.0.3: 2005 + arraybuffer.prototype.slice@1.0.4: 1683 2006 dependencies: 1684 - array-buffer-byte-length: 1.0.1 1685 - call-bind: 1.0.7 2007 + array-buffer-byte-length: 1.0.2 2008 + call-bind: 1.0.8 1686 2009 define-properties: 1.2.1 1687 - es-abstract: 1.23.3 2010 + es-abstract: 1.23.9 1688 2011 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 2012 + get-intrinsic: 1.3.0 2013 + is-array-buffer: 3.0.5 1692 2014 1693 2015 astring@1.9.0: {} 2016 + 2017 + async-function@1.0.0: {} 1694 2018 1695 2019 available-typed-arrays@1.0.7: 1696 2020 dependencies: 1697 - possible-typed-array-names: 1.0.0 2021 + possible-typed-array-names: 1.1.0 1698 2022 1699 2023 balanced-match@1.0.2: {} 1700 2024 ··· 1718 2042 base64-js: 1.5.1 1719 2043 ieee754: 1.2.1 1720 2044 1721 - call-bind@1.0.7: 2045 + cac@6.7.14: {} 2046 + 2047 + call-bind-apply-helpers@1.0.2: 1722 2048 dependencies: 1723 - es-define-property: 1.0.0 1724 2049 es-errors: 1.3.0 1725 2050 function-bind: 1.1.2 1726 - get-intrinsic: 1.2.4 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 1727 2057 set-function-length: 1.2.2 1728 2058 2059 + call-bound@1.0.4: 2060 + dependencies: 2061 + call-bind-apply-helpers: 1.0.2 2062 + get-intrinsic: 1.3.0 2063 + 1729 2064 callsites@3.1.0: {} 1730 2065 1731 2066 chalk@4.1.2: ··· 1741 2076 1742 2077 concat-map@0.0.1: {} 1743 2078 1744 - cross-spawn@7.0.3: 2079 + cross-spawn@7.0.6: 1745 2080 dependencies: 1746 2081 path-key: 3.1.1 1747 2082 shebang-command: 2.0.0 1748 2083 which: 2.0.2 1749 2084 1750 - csstype@3.1.2: {} 1751 - 1752 2085 csstype@3.1.3: {} 1753 2086 1754 - data-view-buffer@1.0.1: 2087 + data-view-buffer@1.0.2: 1755 2088 dependencies: 1756 - call-bind: 1.0.7 2089 + call-bound: 1.0.4 1757 2090 es-errors: 1.3.0 1758 - is-data-view: 1.0.1 2091 + is-data-view: 1.0.2 1759 2092 1760 - data-view-byte-length@1.0.1: 2093 + data-view-byte-length@1.0.2: 1761 2094 dependencies: 1762 - call-bind: 1.0.7 2095 + call-bound: 1.0.4 1763 2096 es-errors: 1.3.0 1764 - is-data-view: 1.0.1 2097 + is-data-view: 1.0.2 1765 2098 1766 - data-view-byte-offset@1.0.0: 2099 + data-view-byte-offset@1.0.1: 1767 2100 dependencies: 1768 - call-bind: 1.0.7 2101 + call-bound: 1.0.4 1769 2102 es-errors: 1.3.0 1770 - is-data-view: 1.0.1 2103 + is-data-view: 1.0.2 1771 2104 1772 - debug@4.3.4: 2105 + debug@4.4.0: 1773 2106 dependencies: 1774 - ms: 2.1.2 2107 + ms: 2.1.3 1775 2108 1776 2109 deep-is@0.1.4: {} 1777 2110 1778 2111 define-data-property@1.1.4: 1779 2112 dependencies: 1780 - es-define-property: 1.0.0 2113 + es-define-property: 1.0.1 1781 2114 es-errors: 1.3.0 1782 - gopd: 1.0.1 2115 + gopd: 1.2.0 1783 2116 1784 2117 define-properties@1.2.1: 1785 2118 dependencies: ··· 1787 2120 has-property-descriptors: 1.0.2 1788 2121 object-keys: 1.1.1 1789 2122 2123 + defu@6.1.4: {} 2124 + 2125 + destr@2.0.4: {} 2126 + 1790 2127 doctrine@2.1.0: 1791 2128 dependencies: 1792 2129 esutils: 2.0.3 1793 2130 1794 - es-abstract@1.23.3: 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: 1795 2138 dependencies: 1796 - array-buffer-byte-length: 1.0.1 1797 - arraybuffer.prototype.slice: 1.0.3 2139 + array-buffer-byte-length: 1.0.2 2140 + arraybuffer.prototype.slice: 1.0.4 1798 2141 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 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 1804 2148 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 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 1811 2156 globalthis: 1.0.4 1812 - gopd: 1.0.1 2157 + gopd: 1.2.0 1813 2158 has-property-descriptors: 1.0.2 1814 - has-proto: 1.0.3 1815 - has-symbols: 1.0.3 2159 + has-proto: 1.2.0 2160 + has-symbols: 1.1.0 1816 2161 hasown: 2.0.2 1817 - internal-slot: 1.0.7 1818 - is-array-buffer: 3.0.4 2162 + internal-slot: 1.1.0 2163 + is-array-buffer: 3.0.5 1819 2164 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 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 1828 2173 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 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 1835 2183 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 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 1842 2190 1843 - es-define-property@1.0.0: 1844 - dependencies: 1845 - get-intrinsic: 1.2.4 2191 + es-define-property@1.0.1: {} 1846 2192 1847 2193 es-errors@1.3.0: {} 1848 2194 1849 - es-iterator-helpers@1.1.0: 2195 + es-iterator-helpers@1.2.1: 1850 2196 dependencies: 1851 - call-bind: 1.0.7 2197 + call-bind: 1.0.8 2198 + call-bound: 1.0.4 1852 2199 define-properties: 1.2.1 1853 - es-abstract: 1.23.3 2200 + es-abstract: 1.23.9 1854 2201 es-errors: 1.3.0 1855 - es-set-tostringtag: 2.0.3 2202 + es-set-tostringtag: 2.1.0 1856 2203 function-bind: 1.1.2 1857 - get-intrinsic: 1.2.4 2204 + get-intrinsic: 1.3.0 1858 2205 globalthis: 1.0.4 2206 + gopd: 1.2.0 1859 2207 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 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 1865 2213 1866 - es-object-atoms@1.0.0: 2214 + es-object-atoms@1.1.1: 1867 2215 dependencies: 1868 2216 es-errors: 1.3.0 1869 2217 1870 - es-set-tostringtag@2.0.3: 2218 + es-set-tostringtag@2.1.0: 1871 2219 dependencies: 1872 - get-intrinsic: 1.2.4 2220 + es-errors: 1.3.0 2221 + get-intrinsic: 1.3.0 1873 2222 has-tostringtag: 1.0.2 1874 2223 hasown: 2.0.2 1875 2224 1876 - es-shim-unscopables@1.0.2: 2225 + es-shim-unscopables@1.1.0: 1877 2226 dependencies: 1878 2227 hasown: 2.0.2 1879 2228 1880 - es-to-primitive@1.2.1: 2229 + es-to-primitive@1.3.0: 1881 2230 dependencies: 1882 2231 is-callable: 1.2.7 1883 - is-date-object: 1.0.5 1884 - is-symbol: 1.0.4 2232 + is-date-object: 1.1.0 2233 + is-symbol: 1.1.1 1885 2234 1886 2235 esbuild-copy-static-files@0.1.0: {} 1887 2236 ··· 1912 2261 1913 2262 escape-string-regexp@4.0.0: {} 1914 2263 1915 - eslint-config-prettier@9.1.0(eslint@9.12.0): 2264 + eslint-config-prettier@9.1.0(eslint@9.23.0(jiti@2.4.2)): 1916 2265 dependencies: 1917 - eslint: 9.12.0 2266 + eslint: 9.23.0(jiti@2.4.2) 1918 2267 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): 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): 1920 2269 dependencies: 1921 - eslint: 9.12.0 2270 + eslint: 9.23.0(jiti@2.4.2) 1922 2271 prettier: 3.1.0 1923 2272 prettier-linter-helpers: 1.0.0 1924 - synckit: 0.9.2 2273 + synckit: 0.11.1 1925 2274 optionalDependencies: 1926 - eslint-config-prettier: 9.1.0(eslint@9.12.0) 2275 + '@types/eslint': 9.6.1 2276 + eslint-config-prettier: 9.1.0(eslint@9.23.0(jiti@2.4.2)) 1927 2277 1928 - eslint-plugin-react@7.37.1(eslint@9.12.0): 2278 + eslint-plugin-react@7.37.5(eslint@9.23.0(jiti@2.4.2)): 1929 2279 dependencies: 1930 2280 array-includes: 3.1.8 1931 2281 array.prototype.findlast: 1.2.5 1932 - array.prototype.flatmap: 1.3.2 2282 + array.prototype.flatmap: 1.3.3 1933 2283 array.prototype.tosorted: 1.1.4 1934 2284 doctrine: 2.1.0 1935 - es-iterator-helpers: 1.1.0 1936 - eslint: 9.12.0 2285 + es-iterator-helpers: 1.2.1 2286 + eslint: 9.23.0(jiti@2.4.2) 1937 2287 estraverse: 5.3.0 1938 2288 hasown: 2.0.2 1939 2289 jsx-ast-utils: 3.3.5 1940 2290 minimatch: 3.1.2 1941 - object.entries: 1.1.8 2291 + object.entries: 1.1.9 1942 2292 object.fromentries: 2.0.8 1943 - object.values: 1.2.0 2293 + object.values: 1.2.1 1944 2294 prop-types: 15.8.1 1945 2295 resolve: 2.0.0-next.5 1946 2296 semver: 6.3.1 1947 - string.prototype.matchall: 4.0.11 2297 + string.prototype.matchall: 4.0.12 1948 2298 string.prototype.repeat: 1.0.0 1949 2299 1950 - eslint-scope@8.1.0: 2300 + eslint-scope@8.3.0: 1951 2301 dependencies: 1952 2302 esrecurse: 4.3.0 1953 2303 estraverse: 5.3.0 1954 2304 1955 2305 eslint-visitor-keys@3.4.3: {} 1956 2306 1957 - eslint-visitor-keys@4.1.0: {} 2307 + eslint-visitor-keys@4.2.0: {} 1958 2308 1959 - eslint@9.12.0: 2309 + eslint@9.23.0(jiti@2.4.2): 1960 2310 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 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 1969 2320 '@humanwhocodes/module-importer': 1.0.1 1970 - '@humanwhocodes/retry': 0.3.1 2321 + '@humanwhocodes/retry': 0.4.2 1971 2322 '@types/estree': 1.0.6 1972 2323 '@types/json-schema': 7.0.15 1973 2324 ajv: 6.12.6 1974 2325 chalk: 4.1.2 1975 - cross-spawn: 7.0.3 1976 - debug: 4.3.4 2326 + cross-spawn: 7.0.6 2327 + debug: 4.4.0 1977 2328 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 2329 + eslint-scope: 8.3.0 2330 + eslint-visitor-keys: 4.2.0 2331 + espree: 10.3.0 2332 + esquery: 1.6.0 1982 2333 esutils: 2.0.3 1983 2334 fast-deep-equal: 3.1.3 1984 2335 file-entry-cache: 8.0.0 1985 2336 find-up: 5.0.0 1986 2337 glob-parent: 6.0.2 1987 - ignore: 5.3.0 2338 + ignore: 5.3.2 1988 2339 imurmurhash: 0.1.4 1989 2340 is-glob: 4.0.3 1990 2341 json-stable-stringify-without-jsonify: 1.0.1 ··· 1992 2343 minimatch: 3.1.2 1993 2344 natural-compare: 1.4.0 1994 2345 optionator: 0.9.3 1995 - text-table: 0.2.0 2346 + optionalDependencies: 2347 + jiti: 2.4.2 1996 2348 transitivePeerDependencies: 1997 2349 - supports-color 1998 2350 1999 - espree@10.2.0: 2351 + espree@10.3.0: 2000 2352 dependencies: 2001 - acorn: 8.12.1 2002 - acorn-jsx: 5.3.2(acorn@8.12.1) 2003 - eslint-visitor-keys: 4.1.0 2353 + acorn: 8.14.1 2354 + acorn-jsx: 5.3.2(acorn@8.14.1) 2355 + eslint-visitor-keys: 4.2.0 2004 2356 2005 - esquery@1.5.0: 2357 + esquery@1.6.0: 2006 2358 dependencies: 2007 2359 estraverse: 5.3.0 2008 2360 ··· 2045 2397 dependencies: 2046 2398 reusify: 1.0.4 2047 2399 2400 + fdir@6.4.3(picomatch@4.0.2): 2401 + optionalDependencies: 2402 + picomatch: 4.0.2 2403 + 2048 2404 file-entry-cache@8.0.0: 2049 2405 dependencies: 2050 2406 flat-cache: 4.0.1 ··· 2053 2409 dependencies: 2054 2410 to-regex-range: 5.0.1 2055 2411 2412 + find-up-simple@1.0.1: {} 2413 + 2056 2414 find-up@5.0.0: 2057 2415 dependencies: 2058 2416 locate-path: 6.0.0 ··· 2065 2423 2066 2424 flatted@3.2.9: {} 2067 2425 2068 - for-each@0.3.3: 2426 + for-each@0.3.5: 2069 2427 dependencies: 2070 2428 is-callable: 1.2.7 2071 2429 2072 2430 function-bind@1.1.2: {} 2073 2431 2074 - function.prototype.name@1.1.6: 2432 + function.prototype.name@1.1.8: 2075 2433 dependencies: 2076 - call-bind: 1.0.7 2434 + call-bind: 1.0.8 2435 + call-bound: 1.0.4 2077 2436 define-properties: 1.2.1 2078 - es-abstract: 1.23.3 2079 2437 functions-have-names: 1.2.3 2438 + hasown: 2.0.2 2439 + is-callable: 1.2.7 2080 2440 2081 2441 functions-have-names@1.2.3: {} 2082 2442 2083 - get-intrinsic@1.2.4: 2443 + fzf@0.5.2: {} 2444 + 2445 + get-intrinsic@1.3.0: 2084 2446 dependencies: 2447 + call-bind-apply-helpers: 1.0.2 2448 + es-define-property: 1.0.1 2085 2449 es-errors: 1.3.0 2450 + es-object-atoms: 1.1.1 2086 2451 function-bind: 1.1.2 2087 - has-proto: 1.0.3 2088 - has-symbols: 1.0.3 2452 + get-proto: 1.0.1 2453 + gopd: 1.2.0 2454 + has-symbols: 1.1.0 2089 2455 hasown: 2.0.2 2456 + math-intrinsics: 1.1.0 2090 2457 2091 - get-symbol-description@1.0.2: 2458 + get-proto@1.0.1: 2092 2459 dependencies: 2093 - call-bind: 1.0.7 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 2094 2466 es-errors: 1.3.0 2095 - get-intrinsic: 1.2.4 2467 + get-intrinsic: 1.3.0 2096 2468 2097 2469 glob-parent@5.1.2: 2098 2470 dependencies: ··· 2107 2479 globalthis@1.0.4: 2108 2480 dependencies: 2109 2481 define-properties: 1.2.1 2110 - gopd: 1.0.1 2482 + gopd: 1.2.0 2111 2483 2112 - gopd@1.0.1: 2113 - dependencies: 2114 - get-intrinsic: 1.2.4 2484 + gopd@1.2.0: {} 2115 2485 2116 2486 graphemer@1.4.0: {} 2117 2487 2118 - has-bigints@1.0.2: {} 2488 + has-bigints@1.1.0: {} 2119 2489 2120 2490 has-flag@4.0.0: {} 2121 2491 2122 2492 has-property-descriptors@1.0.2: 2123 2493 dependencies: 2124 - es-define-property: 1.0.0 2494 + es-define-property: 1.0.1 2125 2495 2126 - has-proto@1.0.3: {} 2496 + has-proto@1.2.0: 2497 + dependencies: 2498 + dunder-proto: 1.0.1 2127 2499 2128 - has-symbols@1.0.3: {} 2500 + has-symbols@1.1.0: {} 2129 2501 2130 2502 has-tostringtag@1.0.2: 2131 2503 dependencies: 2132 - has-symbols: 1.0.3 2504 + has-symbols: 1.1.0 2133 2505 2134 2506 hasown@2.0.2: 2135 2507 dependencies: ··· 2138 2510 husky@8.0.3: {} 2139 2511 2140 2512 ieee754@1.2.1: {} 2141 - 2142 - ignore@5.3.0: {} 2143 2513 2144 2514 ignore@5.3.2: {} 2145 2515 ··· 2150 2520 2151 2521 imurmurhash@0.1.4: {} 2152 2522 2153 - internal-slot@1.0.7: 2523 + internal-slot@1.1.0: 2154 2524 dependencies: 2155 2525 es-errors: 1.3.0 2156 2526 hasown: 2.0.2 2157 - side-channel: 1.0.6 2527 + side-channel: 1.1.0 2158 2528 2159 - is-array-buffer@3.0.4: 2529 + is-array-buffer@3.0.5: 2160 2530 dependencies: 2161 - call-bind: 1.0.7 2162 - get-intrinsic: 1.2.4 2531 + call-bind: 1.0.8 2532 + call-bound: 1.0.4 2533 + get-intrinsic: 1.3.0 2163 2534 2164 - is-async-function@2.0.0: 2535 + is-async-function@2.1.1: 2165 2536 dependencies: 2537 + async-function: 1.0.0 2538 + call-bound: 1.0.4 2539 + get-proto: 1.0.1 2166 2540 has-tostringtag: 1.0.2 2541 + safe-regex-test: 1.1.0 2167 2542 2168 - is-bigint@1.0.4: 2543 + is-bigint@1.1.0: 2169 2544 dependencies: 2170 - has-bigints: 1.0.2 2545 + has-bigints: 1.1.0 2171 2546 2172 - is-boolean-object@1.1.2: 2547 + is-boolean-object@1.2.2: 2173 2548 dependencies: 2174 - call-bind: 1.0.7 2549 + call-bound: 1.0.4 2175 2550 has-tostringtag: 1.0.2 2176 2551 2177 2552 is-callable@1.2.7: {} 2178 2553 2179 - is-core-module@2.15.1: 2554 + is-core-module@2.16.1: 2180 2555 dependencies: 2181 2556 hasown: 2.0.2 2182 2557 2183 - is-data-view@1.0.1: 2558 + is-data-view@1.0.2: 2184 2559 dependencies: 2185 - is-typed-array: 1.1.13 2560 + call-bound: 1.0.4 2561 + get-intrinsic: 1.3.0 2562 + is-typed-array: 1.1.15 2186 2563 2187 - is-date-object@1.0.5: 2564 + is-date-object@1.1.0: 2188 2565 dependencies: 2566 + call-bound: 1.0.4 2189 2567 has-tostringtag: 1.0.2 2190 2568 2191 2569 is-extglob@2.1.1: {} 2192 2570 2193 - is-finalizationregistry@1.0.2: 2571 + is-finalizationregistry@1.1.1: 2194 2572 dependencies: 2195 - call-bind: 1.0.7 2573 + call-bound: 1.0.4 2196 2574 2197 - is-generator-function@1.0.10: 2575 + is-generator-function@1.1.0: 2198 2576 dependencies: 2577 + call-bound: 1.0.4 2578 + get-proto: 1.0.1 2199 2579 has-tostringtag: 1.0.2 2580 + safe-regex-test: 1.1.0 2200 2581 2201 2582 is-glob@4.0.3: 2202 2583 dependencies: ··· 2204 2585 2205 2586 is-map@2.0.3: {} 2206 2587 2207 - is-negative-zero@2.0.3: {} 2208 - 2209 - is-number-object@1.0.7: 2588 + is-number-object@1.1.1: 2210 2589 dependencies: 2590 + call-bound: 1.0.4 2211 2591 has-tostringtag: 1.0.2 2212 2592 2213 2593 is-number@7.0.0: {} 2214 2594 2215 - is-regex@1.1.4: 2595 + is-regex@1.2.1: 2216 2596 dependencies: 2217 - call-bind: 1.0.7 2597 + call-bound: 1.0.4 2598 + gopd: 1.2.0 2218 2599 has-tostringtag: 1.0.2 2600 + hasown: 2.0.2 2219 2601 2220 2602 is-set@2.0.3: {} 2221 2603 2222 - is-shared-array-buffer@1.0.3: 2604 + is-shared-array-buffer@1.0.4: 2223 2605 dependencies: 2224 - call-bind: 1.0.7 2606 + call-bound: 1.0.4 2225 2607 2226 - is-string@1.0.7: 2608 + is-string@1.1.1: 2227 2609 dependencies: 2610 + call-bound: 1.0.4 2228 2611 has-tostringtag: 1.0.2 2229 2612 2230 - is-symbol@1.0.4: 2613 + is-symbol@1.1.1: 2231 2614 dependencies: 2232 - has-symbols: 1.0.3 2615 + call-bound: 1.0.4 2616 + has-symbols: 1.1.0 2617 + safe-regex-test: 1.1.0 2233 2618 2234 - is-typed-array@1.1.13: 2619 + is-typed-array@1.1.15: 2235 2620 dependencies: 2236 - which-typed-array: 1.1.15 2621 + which-typed-array: 1.1.19 2237 2622 2238 2623 is-weakmap@2.0.2: {} 2239 2624 2240 - is-weakref@1.0.2: 2625 + is-weakref@1.1.1: 2241 2626 dependencies: 2242 - call-bind: 1.0.7 2627 + call-bound: 1.0.4 2243 2628 2244 - is-weakset@2.0.3: 2629 + is-weakset@2.0.4: 2245 2630 dependencies: 2246 - call-bind: 1.0.7 2247 - get-intrinsic: 1.2.4 2631 + call-bound: 1.0.4 2632 + get-intrinsic: 1.3.0 2248 2633 2249 2634 isarray@2.0.5: {} 2250 2635 2251 2636 isexe@2.0.0: {} 2252 2637 2253 - iterator.prototype@1.1.3: 2638 + iterator.prototype@1.1.5: 2254 2639 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 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 2259 2645 set-function-name: 2.0.2 2260 2646 2647 + jiti@2.4.2: {} 2648 + 2261 2649 js-tokens@4.0.0: {} 2262 2650 2263 2651 js-yaml@4.1.0: ··· 2273 2661 jsx-ast-utils@3.3.5: 2274 2662 dependencies: 2275 2663 array-includes: 3.1.8 2276 - array.prototype.flat: 1.3.2 2277 - object.assign: 4.1.5 2278 - object.values: 1.2.0 2664 + array.prototype.flat: 1.3.3 2665 + object.assign: 4.1.7 2666 + object.values: 1.2.1 2279 2667 2280 2668 keyv@4.5.4: 2281 2669 dependencies: ··· 2296 2684 dependencies: 2297 2685 js-tokens: 4.0.0 2298 2686 2687 + math-intrinsics@1.1.0: {} 2688 + 2299 2689 merge2@1.4.1: {} 2300 2690 2301 2691 meriyah@6.0.1: {} ··· 2306 2696 dependencies: 2307 2697 braces: 3.0.3 2308 2698 picomatch: 2.3.1 2699 + 2700 + mimic-function@5.0.1: {} 2309 2701 2310 2702 minimatch@3.1.2: 2311 2703 dependencies: ··· 2315 2707 dependencies: 2316 2708 brace-expansion: 2.0.1 2317 2709 2318 - ms@2.1.2: {} 2710 + ms@2.1.3: {} 2319 2711 2320 2712 nanotar@0.1.1: {} 2321 2713 2322 2714 natural-compare@1.4.0: {} 2323 2715 2716 + node-fetch-native@1.6.6: {} 2717 + 2324 2718 object-assign@4.1.1: {} 2325 2719 2326 - object-inspect@1.13.2: {} 2720 + object-inspect@1.13.4: {} 2327 2721 2328 2722 object-keys@1.1.1: {} 2329 2723 2330 - object.assign@4.1.5: 2724 + object.assign@4.1.7: 2331 2725 dependencies: 2332 - call-bind: 1.0.7 2726 + call-bind: 1.0.8 2727 + call-bound: 1.0.4 2333 2728 define-properties: 1.2.1 2334 - has-symbols: 1.0.3 2729 + es-object-atoms: 1.1.1 2730 + has-symbols: 1.1.0 2335 2731 object-keys: 1.1.1 2336 2732 2337 - object.entries@1.1.8: 2733 + object.entries@1.1.9: 2338 2734 dependencies: 2339 - call-bind: 1.0.7 2735 + call-bind: 1.0.8 2736 + call-bound: 1.0.4 2340 2737 define-properties: 1.2.1 2341 - es-object-atoms: 1.0.0 2738 + es-object-atoms: 1.1.1 2342 2739 2343 2740 object.fromentries@2.0.8: 2344 2741 dependencies: 2345 - call-bind: 1.0.7 2742 + call-bind: 1.0.8 2346 2743 define-properties: 1.2.1 2347 - es-abstract: 1.23.3 2348 - es-object-atoms: 1.0.0 2744 + es-abstract: 1.23.9 2745 + es-object-atoms: 1.1.1 2349 2746 2350 - object.values@1.2.0: 2747 + object.values@1.2.1: 2351 2748 dependencies: 2352 - call-bind: 1.0.7 2749 + call-bind: 1.0.8 2750 + call-bound: 1.0.4 2353 2751 define-properties: 1.2.1 2354 - es-object-atoms: 1.0.0 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 2355 2763 2356 2764 optionator@0.9.3: 2357 2765 dependencies: ··· 2361 2769 levn: 0.4.1 2362 2770 prelude-ls: 1.2.1 2363 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 2364 2778 2365 2779 p-limit@3.1.0: 2366 2780 dependencies: ··· 2370 2784 dependencies: 2371 2785 p-limit: 3.1.0 2372 2786 2787 + package-manager-detector@1.1.0: {} 2788 + 2373 2789 parent-module@1.0.1: 2374 2790 dependencies: 2375 2791 callsites: 3.1.0 ··· 2380 2796 2381 2797 path-parse@1.0.7: {} 2382 2798 2799 + pathe@2.0.3: {} 2800 + 2383 2801 picomatch@2.3.1: {} 2384 2802 2385 - possible-typed-array-names@1.0.0: {} 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: {} 2386 2810 2387 2811 prelude-ls@1.2.1: {} 2388 2812 ··· 2402 2826 2403 2827 punycode@2.3.1: {} 2404 2828 2829 + quansync@0.2.10: {} 2830 + 2405 2831 queue-microtask@1.2.3: {} 2406 2832 2407 2833 react-is@16.13.1: {} ··· 2414 2840 process: 0.11.10 2415 2841 string_decoder: 1.3.0 2416 2842 2417 - reflect.getprototypeof@1.0.6: 2843 + reflect.getprototypeof@1.0.10: 2418 2844 dependencies: 2419 - call-bind: 1.0.7 2845 + call-bind: 1.0.8 2420 2846 define-properties: 1.2.1 2421 - es-abstract: 1.23.3 2847 + es-abstract: 1.23.9 2422 2848 es-errors: 1.3.0 2423 - get-intrinsic: 1.2.4 2424 - globalthis: 1.0.4 2425 - which-builtin-type: 1.1.4 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 2426 2853 2427 - regexp.prototype.flags@1.5.3: 2854 + regexp.prototype.flags@1.5.4: 2428 2855 dependencies: 2429 - call-bind: 1.0.7 2856 + call-bind: 1.0.8 2430 2857 define-properties: 1.2.1 2431 2858 es-errors: 1.3.0 2859 + get-proto: 1.0.1 2860 + gopd: 1.2.0 2432 2861 set-function-name: 2.0.2 2433 2862 2434 2863 resolve-from@4.0.0: {} 2435 2864 2436 2865 resolve@2.0.0-next.5: 2437 2866 dependencies: 2438 - is-core-module: 2.15.1 2867 + is-core-module: 2.16.1 2439 2868 path-parse: 1.0.7 2440 2869 supports-preserve-symlinks-flag: 1.0.0 2441 2870 2871 + restore-cursor@5.1.0: 2872 + dependencies: 2873 + onetime: 7.0.0 2874 + signal-exit: 4.1.0 2875 + 2442 2876 reusify@1.0.4: {} 2443 2877 2444 2878 run-parallel@1.2.0: 2445 2879 dependencies: 2446 2880 queue-microtask: 1.2.3 2447 2881 2448 - safe-array-concat@1.1.2: 2882 + safe-array-concat@1.1.3: 2449 2883 dependencies: 2450 - call-bind: 1.0.7 2451 - get-intrinsic: 1.2.4 2452 - has-symbols: 1.0.3 2884 + call-bind: 1.0.8 2885 + call-bound: 1.0.4 2886 + get-intrinsic: 1.3.0 2887 + has-symbols: 1.1.0 2453 2888 isarray: 2.0.5 2454 2889 2455 - safe-buffer@5.1.2: {} 2456 - 2457 2890 safe-buffer@5.2.1: {} 2458 2891 2459 - safe-regex-test@1.0.3: 2892 + safe-push-apply@1.0.0: 2460 2893 dependencies: 2461 - call-bind: 1.0.7 2462 2894 es-errors: 1.3.0 2463 - is-regex: 1.1.4 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 2464 2902 2465 2903 semver@6.3.1: {} 2466 2904 2467 - semver@7.6.3: {} 2905 + semver@7.7.1: {} 2468 2906 2469 2907 set-function-length@1.2.2: 2470 2908 dependencies: 2471 2909 define-data-property: 1.1.4 2472 2910 es-errors: 1.3.0 2473 2911 function-bind: 1.1.2 2474 - get-intrinsic: 1.2.4 2475 - gopd: 1.0.1 2912 + get-intrinsic: 1.3.0 2913 + gopd: 1.2.0 2476 2914 has-property-descriptors: 1.0.2 2477 2915 2478 2916 set-function-name@2.0.2: ··· 2482 2920 functions-have-names: 1.2.3 2483 2921 has-property-descriptors: 1.0.2 2484 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 + 2485 2929 shebang-command@2.0.0: 2486 2930 dependencies: 2487 2931 shebang-regex: 3.0.0 2488 2932 2489 2933 shebang-regex@3.0.0: {} 2490 2934 2491 - side-channel@1.0.6: 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: 2492 2956 dependencies: 2493 - call-bind: 1.0.7 2494 2957 es-errors: 1.3.0 2495 - get-intrinsic: 1.2.4 2496 - object-inspect: 1.13.2 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: {} 2497 2964 2498 2965 standalone-electron-types@1.0.0: 2499 2966 dependencies: 2500 2967 '@types/node': 18.17.17 2501 2968 2502 - string.prototype.matchall@4.0.11: 2969 + string.prototype.matchall@4.0.12: 2503 2970 dependencies: 2504 - call-bind: 1.0.7 2971 + call-bind: 1.0.8 2972 + call-bound: 1.0.4 2505 2973 define-properties: 1.2.1 2506 - es-abstract: 1.23.3 2974 + es-abstract: 1.23.9 2507 2975 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 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 2514 2982 set-function-name: 2.0.2 2515 - side-channel: 1.0.6 2983 + side-channel: 1.1.0 2516 2984 2517 2985 string.prototype.repeat@1.0.0: 2518 2986 dependencies: 2519 2987 define-properties: 1.2.1 2520 - es-abstract: 1.23.3 2988 + es-abstract: 1.23.9 2521 2989 2522 - string.prototype.trim@1.2.9: 2990 + string.prototype.trim@1.2.10: 2523 2991 dependencies: 2524 - call-bind: 1.0.7 2992 + call-bind: 1.0.8 2993 + call-bound: 1.0.4 2994 + define-data-property: 1.1.4 2525 2995 define-properties: 1.2.1 2526 - es-abstract: 1.23.3 2527 - es-object-atoms: 1.0.0 2996 + es-abstract: 1.23.9 2997 + es-object-atoms: 1.1.1 2998 + has-property-descriptors: 1.0.2 2528 2999 2529 - string.prototype.trimend@1.0.8: 3000 + string.prototype.trimend@1.0.9: 2530 3001 dependencies: 2531 - call-bind: 1.0.7 3002 + call-bind: 1.0.8 3003 + call-bound: 1.0.4 2532 3004 define-properties: 1.2.1 2533 - es-object-atoms: 1.0.0 3005 + es-object-atoms: 1.1.1 2534 3006 2535 3007 string.prototype.trimstart@1.0.8: 2536 3008 dependencies: 2537 - call-bind: 1.0.7 3009 + call-bind: 1.0.8 2538 3010 define-properties: 1.2.1 2539 - es-object-atoms: 1.0.0 3011 + es-object-atoms: 1.1.1 2540 3012 2541 3013 string_decoder@1.3.0: 2542 3014 dependencies: ··· 2550 3022 2551 3023 supports-preserve-symlinks-flag@1.0.0: {} 2552 3024 2553 - synckit@0.9.2: 3025 + synckit@0.11.1: 3026 + dependencies: 3027 + '@pkgr/core': 0.2.0 3028 + tslib: 2.8.1 3029 + 3030 + taze@19.0.4: 2554 3031 dependencies: 2555 - '@pkgr/core': 0.1.1 2556 - tslib: 2.7.0 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: {} 2557 3046 2558 - text-table@0.2.0: {} 3047 + tinyglobby@0.2.12: 3048 + dependencies: 3049 + fdir: 6.4.3(picomatch@4.0.2) 3050 + picomatch: 4.0.2 2559 3051 2560 3052 to-regex-range@5.0.1: 2561 3053 dependencies: 2562 3054 is-number: 7.0.0 2563 3055 2564 - ts-api-utils@1.3.0(typescript@5.3.2): 3056 + ts-api-utils@2.1.0(typescript@5.8.2): 2565 3057 dependencies: 2566 - typescript: 5.3.2 3058 + typescript: 5.8.2 2567 3059 2568 - tslib@2.7.0: {} 3060 + tslib@2.8.1: {} 2569 3061 2570 3062 type-check@0.4.0: 2571 3063 dependencies: 2572 3064 prelude-ls: 1.2.1 2573 3065 2574 - typed-array-buffer@1.0.2: 3066 + typed-array-buffer@1.0.3: 2575 3067 dependencies: 2576 - call-bind: 1.0.7 3068 + call-bound: 1.0.4 2577 3069 es-errors: 1.3.0 2578 - is-typed-array: 1.1.13 3070 + is-typed-array: 1.1.15 2579 3071 2580 - typed-array-byte-length@1.0.1: 3072 + typed-array-byte-length@1.0.3: 2581 3073 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 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 2587 3079 2588 - typed-array-byte-offset@1.0.2: 3080 + typed-array-byte-offset@1.0.4: 2589 3081 dependencies: 2590 3082 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 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 2596 3089 2597 - typed-array-length@1.0.6: 3090 + typed-array-length@1.0.7: 2598 3091 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 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 2605 3098 2606 - typescript-eslint@8.8.1(eslint@9.12.0)(typescript@5.3.2): 3099 + typescript-eslint@8.29.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2): 2607 3100 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 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 2613 3106 transitivePeerDependencies: 2614 - - eslint 2615 3107 - supports-color 2616 3108 2617 - typescript@5.3.2: {} 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 2618 3119 2619 - unbox-primitive@1.0.2: 3120 + unconfig@7.3.1: 2620 3121 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 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: {} 2625 3128 2626 - undici-types@6.19.8: {} 3129 + undici-types@6.21.0: {} 2627 3130 2628 3131 uri-js@4.4.1: 2629 3132 dependencies: 2630 3133 punycode: 2.3.1 2631 3134 2632 - utilium@0.7.1: 3135 + utilium@1.10.1: 2633 3136 dependencies: 2634 3137 eventemitter3: 5.0.1 3138 + optionalDependencies: 3139 + '@xterm/xterm': 5.5.0 2635 3140 2636 - which-boxed-primitive@1.0.2: 3141 + which-boxed-primitive@1.1.1: 2637 3142 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 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 2643 3148 2644 - which-builtin-type@1.1.4: 3149 + which-builtin-type@1.2.1: 2645 3150 dependencies: 2646 - function.prototype.name: 1.1.6 3151 + call-bound: 1.0.4 3152 + function.prototype.name: 1.1.8 2647 3153 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 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 2654 3160 isarray: 2.0.5 2655 - which-boxed-primitive: 1.0.2 3161 + which-boxed-primitive: 1.1.1 2656 3162 which-collection: 1.0.2 2657 - which-typed-array: 1.1.15 3163 + which-typed-array: 1.1.19 2658 3164 2659 3165 which-collection@1.0.2: 2660 3166 dependencies: 2661 3167 is-map: 2.0.3 2662 3168 is-set: 2.0.3 2663 3169 is-weakmap: 2.0.2 2664 - is-weakset: 2.0.3 3170 + is-weakset: 2.0.4 2665 3171 2666 - which-typed-array@1.1.15: 3172 + which-typed-array@1.1.19: 2667 3173 dependencies: 2668 3174 available-typed-arrays: 1.0.7 2669 - call-bind: 1.0.7 2670 - for-each: 0.3.3 2671 - gopd: 1.0.1 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 2672 3180 has-tostringtag: 1.0.2 2673 3181 2674 3182 which@2.0.2: 2675 3183 dependencies: 2676 3184 isexe: 2.0.0 2677 3185 3186 + yaml@2.7.1: {} 3187 + 2678 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 1 packages: 2 - - "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 1 { 2 + "extends": ["./tsconfig.base.json"], 2 3 "compilerOptions": { 3 - "target": "es2022", 4 - "module": "es2020", 5 - "esModuleInterop": true, 6 - "forceConsistentCasingInFileNames": true, 7 - "strict": true, 8 - "moduleResolution": "bundler", 9 4 "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 5 + "noEmit": true 18 6 }, 19 - "include": ["./packages/**/*", "./env.d.ts"], 20 - "exclude": ["node_modules"] 7 + "exclude": [ 8 + "**/node_modules/**", 9 + "**/dist/**", 10 + "**/build/**" 11 + ] 21 12 }