From 3ab4cd5d05132e5913c46b2ead0ab3f10048ecb0 Mon Sep 17 00:00:00 2001 From: Angelos Bouklis <53124886+ArjixWasTaken@users.noreply.github.com> Date: Sun, 26 Nov 2023 01:17:24 +0200 Subject: [PATCH] change plugin system --- .eslintrc.js | 66 +- .gitignore | 1 + electron.vite.config.ts | 48 +- package.json | 8 +- pnpm-lock.yaml | 608 +++++++++++++----- src/config/index.ts | 66 +- src/config/store.ts | 45 +- src/index.ts | 345 ++++++---- src/loader/main.ts | 166 ++--- src/loader/menu.ts | 61 +- src/loader/preload.ts | 87 ++- src/loader/renderer.ts | 101 ++- src/menu.ts | 273 ++++---- src/plugins/audio-compressor.ts | 25 + src/plugins/audio-compressor/index.ts | 17 - src/plugins/audio-compressor/renderer.ts | 24 - src/plugins/blur-nav-bar/index.ts | 19 +- src/plugins/bypass-age-restrictions/index.ts | 18 +- .../bypass-age-restrictions/renderer.ts | 8 - src/plugins/captions-selector/index.ts | 58 +- src/plugins/captions-selector/main.ts | 22 - src/plugins/captions-selector/menu.ts | 26 - src/plugins/utils/main/index.ts | 1 - src/plugins/utils/main/plugin.ts | 18 - src/preload.ts | 52 +- src/renderer.ts | 96 +-- src/types/contexts.ts | 33 + src/types/plugins.ts | 38 ++ src/utils/index.ts | 64 ++ src/virtual-module.d.ts | 36 +- tsconfig.json | 13 +- vite-plugins/plugin-importer.ts | 63 ++ vite-plugins/plugin-loader.ts | 105 +++ .../plugin-virtual-module-generator.ts | 49 -- 34 files changed, 1670 insertions(+), 990 deletions(-) create mode 100644 src/plugins/audio-compressor.ts delete mode 100644 src/plugins/audio-compressor/index.ts delete mode 100644 src/plugins/audio-compressor/renderer.ts delete mode 100644 src/plugins/bypass-age-restrictions/renderer.ts delete mode 100644 src/plugins/captions-selector/main.ts delete mode 100644 src/plugins/captions-selector/menu.ts delete mode 100644 src/plugins/utils/main/plugin.ts create mode 100644 src/types/contexts.ts create mode 100644 src/types/plugins.ts create mode 100644 src/utils/index.ts create mode 100644 vite-plugins/plugin-importer.ts create mode 100644 vite-plugins/plugin-loader.ts delete mode 100644 vite-plugins/plugin-virtual-module-generator.ts diff --git a/.eslintrc.js b/.eslintrc.js index 59f3401f..a64e42d2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,8 +1,8 @@ module.exports = { extends: [ + 'plugin:import/typescript', 'eslint:recommended', 'plugin:import/recommended', - 'plugin:import/typescript', 'plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended-requiring-type-checking', @@ -13,30 +13,51 @@ module.exports = { project: './tsconfig.json', tsconfigRootDir: __dirname, sourceType: 'module', - ecmaVersion: 'latest' + ecmaVersion: 'latest', }, rules: { 'arrow-parens': ['error', 'always'], 'object-curly-spacing': ['error', 'always'], '@typescript-eslint/no-floating-promises': 'off', - '@typescript-eslint/no-misused-promises': ['off', { checksVoidReturn: false }], + '@typescript-eslint/no-misused-promises': [ + 'off', + { checksVoidReturn: false }, + ], '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], - "@typescript-eslint/no-non-null-assertion": "off", + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', 'import/first': 'error', 'import/newline-after-import': 'error', 'import/no-default-export': 'off', 'import/no-duplicates': 'error', - 'import/no-unresolved': ['error', { ignore: ['^virtual:', '\\?inline$', '\\?raw$', '\\?asset&asarUnpack', '^youtubei.js$'] }], + 'import/no-unresolved': [ + 'error', + { + ignore: [ + '^virtual:', + '\\?inline$', + '\\?raw$', + '\\?asset&asarUnpack', + '^youtubei.js$', + ], + }, + ], 'import/order': [ 'error', { - 'groups': ['builtin', 'external', ['internal', 'index', 'sibling'], 'parent', 'type'], + groups: [ + 'builtin', + 'external', + ['internal', 'index', 'sibling'], + 'parent', + 'type', + ], 'newlines-between': 'always-and-inside-groups', - 'alphabetize': {order: 'ignore', caseInsensitive: false} - } + alphabetize: { order: 'ignore', caseInsensitive: false }, + }, ], 'import/prefer-default-export': 'off', - 'camelcase': ['error', {properties: 'never'}], + camelcase: ['error', { properties: 'never' }], 'class-methods-use-this': 'off', 'lines-around-comment': [ 'error', @@ -49,17 +70,21 @@ module.exports = { ], 'max-len': 'off', 'no-mixed-operators': 'error', - 'no-multi-spaces': ['error', {ignoreEOLComments: true}], + 'no-multi-spaces': ['error', { ignoreEOLComments: true }], 'no-tabs': 'error', 'no-void': 'error', 'no-empty': 'off', 'prefer-promise-reject-errors': 'off', - 'quotes': ['error', 'single', { - avoidEscape: true, - allowTemplateLiterals: false, - }], + quotes: [ + 'error', + 'single', + { + avoidEscape: true, + allowTemplateLiterals: false, + }, + ], 'quote-props': ['error', 'consistent'], - 'semi': ['error', 'always'], + semi: ['error', 'always'], }, env: { browser: true, @@ -67,4 +92,15 @@ module.exports = { es6: true, }, ignorePatterns: ['dist', 'node_modules'], + root: true, + settings: { + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + 'import/resolver': { + typescript: { + alwaysTryTypes: true, + }, + }, + }, }; diff --git a/.gitignore b/.gitignore index ec2a06da..6cb8c059 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ electron-builder.yml !.yarn/releases !.yarn/sdks !.yarn/versions +.vite-inspect diff --git a/electron.vite.config.ts b/electron.vite.config.ts index 5d8dafae..1dd2b941 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -1,8 +1,12 @@ +import { fileURLToPath, URL } from 'node:url'; + import { defineConfig, defineViteConfig } from 'electron-vite'; import builtinModules from 'builtin-modules'; import viteResolve from 'vite-plugin-resolve'; +import Inspect from 'vite-plugin-inspect'; -import { pluginVirtualModuleGenerator } from './vite-plugins/plugin-virtual-module-generator'; +import { pluginVirtualModuleGenerator } from './vite-plugins/plugin-importer'; +import pluginLoader from './vite-plugins/plugin-loader'; import type { UserConfig } from 'vite'; @@ -10,10 +14,9 @@ export default defineConfig({ main: defineViteConfig(({ mode }) => { const commonConfig: UserConfig = { plugins: [ + pluginLoader('backend'), viteResolve({ - 'virtual:PluginBuilders': pluginVirtualModuleGenerator('index'), - 'virtual:MainPlugins': pluginVirtualModuleGenerator('main'), - 'virtual:MenuPlugins': pluginVirtualModuleGenerator('menu'), + 'virtual:plugins': pluginVirtualModuleGenerator('main'), }), ], publicDir: 'assets', @@ -31,9 +34,18 @@ export default defineConfig({ input: './src/index.ts', }, }, + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + '@assets': fileURLToPath(new URL('./assets', import.meta.url)), + }, + }, }; if (mode === 'development') { + commonConfig.plugins?.push( + Inspect({ build: true, outputDir: '.vite-inspect/backend' }), + ); return commonConfig; } @@ -49,9 +61,9 @@ export default defineConfig({ preload: defineViteConfig(({ mode }) => { const commonConfig: UserConfig = { plugins: [ + pluginLoader('preload'), viteResolve({ - 'virtual:PluginBuilders': pluginVirtualModuleGenerator('index'), - 'virtual:PreloadPlugins': pluginVirtualModuleGenerator('preload'), + 'virtual:plugins': pluginVirtualModuleGenerator('preload'), }), ], build: { @@ -66,11 +78,20 @@ export default defineConfig({ rollupOptions: { external: ['electron', 'custom-electron-prompt', ...builtinModules], input: './src/preload.ts', - } + }, + }, + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + '@assets': fileURLToPath(new URL('./assets', import.meta.url)), + }, }, }; if (mode === 'development') { + commonConfig.plugins?.push( + Inspect({ build: true, outputDir: '.vite-inspect/preload' }), + ); return commonConfig; } @@ -86,9 +107,9 @@ export default defineConfig({ renderer: defineViteConfig(({ mode }) => { const commonConfig: UserConfig = { plugins: [ + pluginLoader('renderer'), viteResolve({ - 'virtual:PluginBuilders': pluginVirtualModuleGenerator('index'), - 'virtual:RendererPlugins': pluginVirtualModuleGenerator('renderer'), + 'virtual:plugins': pluginVirtualModuleGenerator('renderer'), }), ], root: './src/', @@ -107,9 +128,18 @@ export default defineConfig({ input: './src/index.html', }, }, + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + '@assets': fileURLToPath(new URL('./assets', import.meta.url)), + }, + }, }; if (mode === 'development') { + commonConfig.plugins?.push( + Inspect({ build: true, outputDir: '.vite-inspect/renderer' }), + ); return commonConfig; } diff --git a/package.json b/package.json index 30c27bbe..ef00b764 100644 --- a/package.json +++ b/package.json @@ -94,11 +94,12 @@ "test": "playwright test", "test:debug": "cross-env DEBUG=pw:*,-pw:test:protocol playwright test", "build": "electron-vite build", + "vite:inspect": "yarpm-pnpm run clean && electron-vite build --mode development && yarpm-pnpm exec serve .vite-inspect", "start": "electron-vite preview", "start:debug": "cross-env ELECTRON_ENABLE_LOGGING=1 yarpm-pnpm run start", "dev": "electron-vite dev --watch", "dev:debug": "cross-env ELECTRON_ENABLE_LOGGING=1 yarpm-pnpm run dev", - "clean": "del-cli dist && del-cli pack", + "clean": "del-cli dist && del-cli pack && del-cli .vite-inspect", "dist": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --win --mac --linux -p never", "dist:linux": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --linux -p never", "dist:mac": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --mac dmg:x64 -p never", @@ -136,6 +137,7 @@ "dependencies": { "@cliqz/adblocker-electron": "1.26.11", "@cliqz/adblocker-electron-preload": "1.26.11", + "@electron-toolkit/tsconfig": "^1.0.1", "@ffmpeg.wasm/core-mt": "0.12.0", "@ffmpeg.wasm/main": "0.12.0", "@foobar404/wave": "2.0.4", @@ -155,6 +157,7 @@ "electron-store": "8.1.0", "electron-unhandled": "4.0.1", "electron-updater": "6.1.4", + "eslint-import-resolver-typescript": "^3.6.1", "fast-average-color": "9.4.0", "fast-equals": "^5.0.1", "filenamify": "6.0.0", @@ -164,7 +167,9 @@ "keyboardevents-areequal": "0.2.2", "node-html-parser": "6.1.11", "node-id3": "0.2.6", + "serve": "^14.2.1", "simple-youtube-age-restriction-bypass": "git+https://github.com/organization/Simple-YouTube-Age-Restriction-Bypass.git#v2.5.8", + "ts-morph": "^20.0.0", "vudio": "2.1.1", "x11": "2.3.0", "youtubei.js": "7.0.0" @@ -194,6 +199,7 @@ "typescript": "5.2.2", "utf-8-validate": "6.0.3", "vite": "4.5.0", + "vite-plugin-inspect": "^0.7.42", "vite-plugin-resolve": "2.5.1", "ws": "8.14.2", "yarpm": "1.2.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6fe005dc..c1ac585f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,6 +19,9 @@ dependencies: '@cliqz/adblocker-electron-preload': specifier: 1.26.11 version: 1.26.11(electron@27.0.4) + '@electron-toolkit/tsconfig': + specifier: ^1.0.1 + version: 1.0.1(@types/node@20.8.6) '@ffmpeg.wasm/core-mt': specifier: 0.12.0 version: 0.12.0 @@ -76,6 +79,9 @@ dependencies: electron-updater: specifier: 6.1.4 version: 6.1.4 + eslint-import-resolver-typescript: + specifier: ^3.6.1 + version: 3.6.1(@typescript-eslint/parser@6.7.5)(eslint-plugin-import@2.29.0)(eslint@8.53.0) fast-average-color: specifier: 9.4.0 version: 9.4.0 @@ -103,9 +109,15 @@ dependencies: node-id3: specifier: 0.2.6 version: 0.2.6 + serve: + specifier: ^14.2.1 + version: 14.2.1 simple-youtube-age-restriction-bypass: specifier: git+https://github.com/organization/Simple-YouTube-Age-Restriction-Bypass.git#v2.5.8 version: github.com/organization/Simple-YouTube-Age-Restriction-Bypass/816a882c68fcfe6cdd9410a6877b88093ed15b28 + ts-morph: + specifier: ^20.0.0 + version: 20.0.0 vudio: specifier: 2.1.1 version: 2.1.1 @@ -164,7 +176,7 @@ devDependencies: version: 8.53.0 eslint-plugin-import: specifier: 2.29.0 - version: 2.29.0(@typescript-eslint/parser@6.7.5)(eslint@8.53.0) + version: 2.29.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0) eslint-plugin-prettier: specifier: 5.0.1 version: 5.0.1(eslint@8.53.0)(prettier@3.0.3) @@ -188,7 +200,10 @@ devDependencies: version: 6.0.3 vite: specifier: 4.5.0 - version: 4.5.0 + version: 4.5.0(@types/node@20.8.6) + vite-plugin-inspect: + specifier: ^0.7.42 + version: 0.7.42(rollup@4.3.0)(vite@4.5.0) vite-plugin-resolve: specifier: 2.5.1 version: 2.5.1 @@ -208,7 +223,6 @@ packages: /@aashutoshrathi/word-wrap@1.2.6: resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} engines: {node: '>=0.10.0'} - dev: true /@ampproject/remapping@2.2.1: resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} @@ -218,6 +232,10 @@ packages: '@jridgewell/trace-mapping': 0.3.19 dev: true + /@antfu/utils@0.7.6: + resolution: {integrity: sha512-pvFiLP2BeOKA/ZOS6jxx4XhKzdVLHDhGlFEaZ2flWWYf2xOqVniqpk38I04DFRyz+L0ASggl7SkItTc+ZLju4w==} + dev: true + /@assemblyscript/loader@0.17.14: resolution: {integrity: sha512-+PVTOfla/0XMLRTQLJFPg4u40XcdTfon6GGea70hBGi8Pd7ZymIXyVUR+vK8wt5Jb4MVKTKPIz43Myyebw5mZA==} dev: false @@ -486,6 +504,14 @@ packages: ajv-keywords: 3.5.2(ajv@6.12.6) dev: true + /@electron-toolkit/tsconfig@1.0.1(@types/node@20.8.6): + resolution: {integrity: sha512-M0Mol3odspvtCuheyujLNAW7bXq7KFNYVMRtpjFa4ZfES4MuklXBC7Nli/omvc+PRKlrklgAGx3l4VakjNo8jg==} + peerDependencies: + '@types/node': '*' + dependencies: + '@types/node': 20.8.6 + dev: false + /@electron/asar@3.2.7: resolution: {integrity: sha512-8FaSCAIiZGYFWyjeevPQt+0e9xCK9YmJ2Rjg5SXgdsXon6cRnU0Yxnbe6CvJbQn26baifur2Y2G5EBayRIsjyg==} engines: {node: '>=10.12.0'} @@ -759,12 +785,10 @@ packages: dependencies: eslint: 8.53.0 eslint-visitor-keys: 3.4.3 - dev: true /@eslint-community/regexpp@4.9.1: resolution: {integrity: sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true /@eslint/eslintrc@2.1.3: resolution: {integrity: sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==} @@ -781,12 +805,10 @@ packages: strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - dev: true /@eslint/js@8.53.0: resolution: {integrity: sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true /@fastify/busboy@2.0.0: resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==} @@ -819,16 +841,13 @@ packages: minimatch: 3.1.2 transitivePeerDependencies: - supports-color - dev: true /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - dev: true /@humanwhocodes/object-schema@2.0.1: resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} - dev: true /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -913,12 +932,10 @@ packages: dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - dev: true /@nodelib/fs.stat@2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - dev: true /@nodelib/fs.walk@1.2.8: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} @@ -926,7 +943,6 @@ packages: dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - dev: true /@nornagon/put@0.0.8: resolution: {integrity: sha512-ugvXJjwF5ldtUpa7D95kruNJ41yFQDEKyF5CW4TgKJnh+W/zmlBzXXeKTyqIgwMFrkePN2JqOBqcF0M0oOunow==} @@ -977,6 +993,10 @@ packages: playwright: 1.39.0 dev: true + /@polka/url@1.0.0-next.23: + resolution: {integrity: sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==} + dev: true + /@remusao/guess-url-type@1.2.1: resolution: {integrity: sha512-rbOqre2jW8STjheOsOaQHLgYBaBZ9Owbdt8NO7WvNZftJlaG3y/K9oOkl8ZUpuFBisIhmBuMEW6c+YrQl5inRA==} dev: false @@ -1006,6 +1026,21 @@ packages: resolution: {integrity: sha512-yvwa+aCyYI/UjeD39BnpMypG8N06l86wIDW1/PAc6ihBRnodIfZDwccxQN3n1t74wduzaz74m4ZMHZnB06567Q==} dev: false + /@rollup/pluginutils@5.0.5(rollup@4.3.0): + resolution: {integrity: sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + rollup: 4.3.0 + dev: true + /@rollup/rollup-android-arm-eabi@4.3.0: resolution: {integrity: sha512-/4pns6BYi8MXdwnXM44yoGAcFYVHL/BYlB2q1HXZ6AzH++LaiEVWFpBWQ/glXhbMbv3E3o09igrHFbP/snhAvA==} cpu: [arm] @@ -1128,6 +1163,15 @@ packages: resolution: {integrity: sha512-AqlrT8YA1o7Ff5wPfMOL0pvL+1X+sw60NN6CcOCqs658emD6RfiXhF7Gu9QcfKBH7ELY2nInLhKSCWVoNL70MQ==} dev: true + /@ts-morph/common@0.21.0: + resolution: {integrity: sha512-ES110Mmne5Vi4ypUKrtVQfXFDtCsDXiUiGxF6ILVlE90dDD4fdpC1LSjydl/ml7xJWKSDZwUYD2zkOePMSrPBA==} + dependencies: + fast-glob: 3.3.1 + minimatch: 7.4.6 + mkdirp: 2.1.6 + path-browserify: 1.0.1 + dev: false + /@types/cacheable-request@6.0.3: resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} dependencies: @@ -1157,6 +1201,10 @@ packages: - supports-color dev: true + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + /@types/filesystem@0.0.33: resolution: {integrity: sha512-2KedRPzwu2K528vFkoXnnWdsG0MtUwPjuA7pRy4vKxlxHEe8qUDZibYHXJKZZr2Cl/ELdCWYqyb/MKwsUuzBWw==} dependencies: @@ -1198,7 +1246,6 @@ packages: /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: true /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} @@ -1304,7 +1351,6 @@ packages: typescript: 5.2.2 transitivePeerDependencies: - supports-color - dev: true /@typescript-eslint/scope-manager@6.10.0: resolution: {integrity: sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==} @@ -1320,7 +1366,6 @@ packages: dependencies: '@typescript-eslint/types': 6.7.5 '@typescript-eslint/visitor-keys': 6.7.5 - dev: true /@typescript-eslint/type-utils@6.10.0(eslint@8.53.0)(typescript@5.2.2): resolution: {integrity: sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==} @@ -1350,7 +1395,6 @@ packages: /@typescript-eslint/types@6.7.5: resolution: {integrity: sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==} engines: {node: ^16.0.0 || >=18.0.0} - dev: true /@typescript-eslint/typescript-estree@6.10.0(typescript@5.2.2): resolution: {integrity: sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==} @@ -1392,7 +1436,6 @@ packages: typescript: 5.2.2 transitivePeerDependencies: - supports-color - dev: true /@typescript-eslint/utils@6.10.0(eslint@8.53.0)(typescript@5.2.2): resolution: {integrity: sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==} @@ -1427,11 +1470,9 @@ packages: dependencies: '@typescript-eslint/types': 6.7.5 eslint-visitor-keys: 3.4.3 - dev: true /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true /@xhayper/discord-rpc@1.0.24(bufferutil@4.0.8)(utf-8-validate@6.0.3): resolution: {integrity: sha512-gzC8OaOSz7cGALSHyyq6nANQvBfyfntbSq+Qh+cNanoKX8ybOj+jWKmDP6PbLVDWoBftTU3JYsWXrLml2df2Hw==} @@ -1451,17 +1492,28 @@ packages: requiresBuild: true dev: true + /@zeit/schemas@2.29.0: + resolution: {integrity: sha512-g5QiLIfbg3pLuYUJPlisNKY+epQJTcMDsOnVNkscrDP1oi7vmJnzOANYJI/1pZcVJ6umUkBv3aFtlg1UvUHGzA==} + dev: false + /abbrev@2.0.0: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + /acorn-jsx@5.3.2(acorn@8.10.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: acorn: 8.10.0 - dev: true /acorn@8.10.0: resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} @@ -1526,7 +1578,15 @@ packages: fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - dev: true + + /ajv@8.11.0: + resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: false /ajv@8.12.0: resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} @@ -1537,6 +1597,12 @@ packages: uri-js: 4.4.1 dev: false + /ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + dependencies: + string-width: 4.2.3 + dev: false + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1602,6 +1668,14 @@ packages: - supports-color dev: true + /arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + dev: false + + /arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: false + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1620,12 +1694,10 @@ packages: es-abstract: 1.22.2 get-intrinsic: 1.2.1 is-string: 1.0.7 - dev: true /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - dev: true /array.prototype.findlastindex@1.2.3: resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} @@ -1636,7 +1708,6 @@ packages: es-abstract: 1.22.2 es-shim-unscopables: 1.0.0 get-intrinsic: 1.2.1 - dev: true /array.prototype.flat@1.3.2: resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} @@ -1646,7 +1717,6 @@ packages: define-properties: 1.2.1 es-abstract: 1.22.2 es-shim-unscopables: 1.0.0 - dev: true /array.prototype.flatmap@1.3.2: resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} @@ -1656,7 +1726,6 @@ packages: define-properties: 1.2.1 es-abstract: 1.22.2 es-shim-unscopables: 1.0.0 - dev: true /arraybuffer.prototype.slice@1.0.2: resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} @@ -1669,7 +1738,6 @@ packages: get-intrinsic: 1.2.1 is-array-buffer: 3.0.2 is-shared-array-buffer: 1.0.2 - dev: true /arrify@1.0.1: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} @@ -1772,6 +1840,20 @@ packages: requiresBuild: true optional: true + /boxen@7.0.0: + resolution: {integrity: sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==} + engines: {node: '>=14.16'} + dependencies: + ansi-align: 3.0.1 + camelcase: 7.0.1 + chalk: 5.0.1 + cli-boxes: 3.0.0 + string-width: 5.1.2 + type-fest: 2.19.0 + widest-line: 4.0.1 + wrap-ansi: 8.1.0 + dev: false + /bplist-parser@0.2.0: resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} engines: {node: '>= 5.10.0'} @@ -1784,7 +1866,6 @@ packages: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true /brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} @@ -1796,7 +1877,6 @@ packages: engines: {node: '>=8'} dependencies: fill-range: 7.0.1 - dev: true /browser-extension-url-match@1.0.0: resolution: {integrity: sha512-LfIs9SYgPjYksjxkgOVYZhxMIroR56isQB3YHTAmzunWuT9qrH6Fxt7TD9/s9MoKo7GP37JZbLlZhL9vwQAk3w==} @@ -1901,6 +1981,11 @@ packages: eel-wasm: 0.0.15 dev: false + /bytes@3.0.0: + resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} + engines: {node: '>= 0.8'} + dev: false + /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -1948,7 +2033,6 @@ packages: /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: true /camelcase-keys@7.0.2: resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==} @@ -1965,10 +2049,22 @@ packages: engines: {node: '>=10'} dev: true + /camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + dev: false + /caniuse-lite@1.0.30001561: resolution: {integrity: sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==} dev: true + /chalk-template@0.4.0: + resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==} + engines: {node: '>=12'} + dependencies: + chalk: 4.1.2 + dev: false + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -1984,7 +2080,11 @@ packages: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true + + /chalk@5.0.1: + resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: false /chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} @@ -2010,6 +2110,11 @@ packages: escape-string-regexp: 5.0.0 dev: true + /cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + dev: false + /cli-truncate@2.1.0: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} engines: {node: '>=8'} @@ -2020,6 +2125,15 @@ packages: dev: true optional: true + /clipboardy@3.0.0: + resolution: {integrity: sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + arch: 2.2.0 + execa: 5.1.1 + is-wsl: 2.2.0 + dev: false + /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -2034,6 +2148,10 @@ packages: dependencies: mimic-response: 1.0.1 + /code-block-writer@12.0.0: + resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==} + dev: false + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -2075,9 +2193,30 @@ packages: engines: {node: '>=0.10.0'} dev: true + /compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /compression@1.7.4: + resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} + engines: {node: '>= 0.8.0'} + dependencies: + accepts: 1.3.8 + bytes: 3.0.0 + compressible: 2.0.18 + debug: 2.6.9 + on-headers: 1.0.2 + safe-buffer: 5.1.2 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true /conf@10.2.0: resolution: {integrity: sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==} @@ -2102,6 +2241,11 @@ packages: typescript: 4.9.5 dev: true + /content-disposition@0.5.2: + resolution: {integrity: sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==} + engines: {node: '>= 0.6'} + dev: false + /convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} dev: true @@ -2191,6 +2335,17 @@ packages: mimic-fn: 3.1.0 dev: false + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + /debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -2200,7 +2355,6 @@ packages: optional: true dependencies: ms: 2.1.3 - dev: true /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} @@ -2260,9 +2414,13 @@ packages: which-typed-array: 1.1.11 dev: false + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: false + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true /deepmerge-ts@5.1.0: resolution: {integrity: sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==} @@ -2361,7 +2519,6 @@ packages: engines: {node: '>=8'} dependencies: path-type: 4.0.0 - dev: true /dmg-builder@24.6.4: resolution: {integrity: sha512-BNcHRc9CWEuI9qt0E655bUBU/j/3wUCYBVKGu1kVpbN5lcUdEJJJeiO0NHK3dgKmra6LUUZlo+mWqc+OCbi0zw==} @@ -2401,14 +2558,12 @@ packages: engines: {node: '>=0.10.0'} dependencies: esutils: 2.0.3 - dev: true /doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} dependencies: esutils: 2.0.3 - dev: true /dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -2615,7 +2770,7 @@ packages: esbuild: 0.18.20 magic-string: 0.30.5 picocolors: 1.0.0 - vite: 4.5.0 + vite: 4.5.0(@types/node@20.8.6) transitivePeerDependencies: - supports-color dev: true @@ -2650,6 +2805,13 @@ packages: dependencies: once: 1.4.0 + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + /ensure-error@2.1.0: resolution: {integrity: sha512-+BMSJHw9gxiJAAp2ZR1E0TNcL09dD3lOvkl7WVm4+Y6xnes/pMetP/TzCHiDduh8ihNDjbGfuYxl7l4PA1xZ8A==} engines: {node: '>=8'} @@ -2673,6 +2835,10 @@ packages: is-arrayish: 0.2.1 dev: true + /error-stack-parser-es@0.1.1: + resolution: {integrity: sha512-g/9rfnvnagiNf+DRMHEVGuGuIBlCIMDFoTA616HaP2l9PlCjGjVhD98PNbVSJvmK4TttqT5mV5tInMhoFgi+aA==} + dev: true + /es-abstract@1.22.2: resolution: {integrity: sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==} engines: {node: '>= 0.4'} @@ -2716,7 +2882,6 @@ packages: typed-array-length: 1.0.4 unbox-primitive: 1.0.2 which-typed-array: 1.1.11 - dev: true /es-get-iterator@1.1.3: resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} @@ -2739,13 +2904,11 @@ packages: get-intrinsic: 1.2.1 has: 1.0.4 has-tostringtag: 1.0.0 - dev: true /es-shim-unscopables@1.0.0: resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} dependencies: has: 1.0.4 - dev: true /es-to-primitive@1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} @@ -2754,7 +2917,6 @@ packages: is-callable: 1.2.7 is-date-object: 1.0.5 is-symbol: 1.0.4 - dev: true /es6-error@4.1.1: resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} @@ -2818,9 +2980,30 @@ packages: resolve: 1.22.8 transitivePeerDependencies: - supports-color - dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-node@0.3.9)(eslint@8.53.0): + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.7.5)(eslint-plugin-import@2.29.0)(eslint@8.53.0): + resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + dependencies: + debug: 4.3.4 + enhanced-resolve: 5.15.0 + eslint: 8.53.0 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0) + fast-glob: 3.3.1 + get-tsconfig: 4.7.2 + is-core-module: 2.13.1 + is-glob: 4.0.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -2845,11 +3028,11 @@ packages: debug: 3.2.7 eslint: 8.53.0 eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.7.5)(eslint-plugin-import@2.29.0)(eslint@8.53.0) transitivePeerDependencies: - supports-color - dev: true - /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.7.5)(eslint@8.53.0): + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0): resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} engines: {node: '>=4'} peerDependencies: @@ -2868,7 +3051,7 @@ packages: doctrine: 2.1.0 eslint: 8.53.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-node@0.3.9)(eslint@8.53.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -2882,7 +3065,6 @@ packages: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - dev: true /eslint-plugin-prettier@5.0.1(eslint@8.53.0)(prettier@3.0.3): resolution: {integrity: sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==} @@ -2910,12 +3092,10 @@ packages: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 - dev: true /eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true /eslint@8.53.0: resolution: {integrity: sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==} @@ -2962,7 +3142,6 @@ packages: text-table: 0.2.0 transitivePeerDependencies: - supports-color - dev: true /espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} @@ -2971,31 +3150,30 @@ packages: acorn: 8.10.0 acorn-jsx: 5.3.2(acorn@8.10.0) eslint-visitor-keys: 3.4.3 - dev: true /esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} dependencies: estraverse: 5.3.0 - dev: true /esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} dependencies: estraverse: 5.3.0 - dev: true /estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} dev: true /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - dev: true /event-stream@3.3.4: resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} @@ -3022,7 +3200,6 @@ packages: onetime: 5.1.2 signal-exit: 3.0.7 strip-final-newline: 2.0.0 - dev: true /execa@7.2.0: resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} @@ -3092,21 +3269,23 @@ packages: glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.5 - dev: true /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true + + /fast-url-parser@1.1.3: + resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==} + dependencies: + punycode: 1.4.1 + dev: false /fastq@1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} dependencies: reusify: 1.0.4 - dev: true /fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} @@ -3126,7 +3305,6 @@ packages: engines: {node: ^10.12.0 || >=12.0.0} dependencies: flat-cache: 3.1.1 - dev: true /file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} @@ -3157,7 +3335,6 @@ packages: engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 - dev: true /find-up@3.0.0: resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} @@ -3172,7 +3349,6 @@ packages: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - dev: true /flat-cache@3.1.1: resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==} @@ -3181,11 +3357,9 @@ packages: flatted: 3.2.9 keyv: 4.5.4 rimraf: 3.0.2 - dev: true /flatted@3.2.9: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} - dev: true /follow-redirects@1.15.3: resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} @@ -3236,6 +3410,15 @@ packages: jsonfile: 6.1.0 universalify: 2.0.0 + /fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + /fs-extra@8.1.0: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} @@ -3268,7 +3451,6 @@ packages: /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true /fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} @@ -3297,7 +3479,6 @@ packages: define-properties: 1.2.1 es-abstract: 1.22.2 functions-have-names: 1.2.3 - dev: true /functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} @@ -3329,7 +3510,6 @@ packages: /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - dev: true /get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} @@ -3337,21 +3517,23 @@ packages: dependencies: call-bind: 1.0.2 get-intrinsic: 1.2.1 - dev: true + + /get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + dependencies: + resolve-pkg-maps: 1.0.0 /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 - dev: true /glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} dependencies: is-glob: 4.0.3 - dev: true /glob@10.3.10: resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} @@ -3373,7 +3555,6 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true /global-agent@3.0.0: resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} @@ -3398,7 +3579,6 @@ packages: engines: {node: '>=8'} dependencies: type-fest: 0.20.2 - dev: true /globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} @@ -3416,7 +3596,6 @@ packages: ignore: 5.2.4 merge2: 1.4.1 slash: 3.0.0 - dev: true /globby@13.2.2: resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} @@ -3455,7 +3634,6 @@ packages: /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true /hard-rejection@2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} @@ -3473,7 +3651,6 @@ packages: /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - dev: true /has-property-descriptors@1.0.0: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} @@ -3503,7 +3680,6 @@ packages: engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 - dev: true /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} @@ -3598,7 +3774,6 @@ packages: /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - dev: true /human-signals@4.3.1: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} @@ -3638,7 +3813,6 @@ packages: /ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} - dev: true /immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} @@ -3650,7 +3824,6 @@ packages: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} @@ -3670,11 +3843,13 @@ packages: dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: true /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: false /internal-slot@1.0.5: resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} @@ -3739,7 +3914,6 @@ packages: resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} dependencies: hasown: 2.0.0 - dev: true /is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} @@ -3751,7 +3925,6 @@ packages: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} hasBin: true - dev: true /is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} @@ -3762,7 +3935,6 @@ packages: /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - dev: true /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} @@ -3773,7 +3945,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 - dev: true /is-inside-container@1.0.0: resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} @@ -3793,7 +3964,6 @@ packages: /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} - dev: true /is-number-object@1.0.7: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} @@ -3804,7 +3974,6 @@ packages: /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - dev: true /is-obj@2.0.0: resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} @@ -3819,7 +3988,6 @@ packages: /is-path-inside@3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} - dev: true /is-path-inside@4.0.0: resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} @@ -3831,6 +3999,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-port-reachable@4.0.0: + resolution: {integrity: sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -3850,7 +4023,6 @@ packages: /is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - dev: true /is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} @@ -3887,7 +4059,6 @@ packages: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: call-bind: 1.0.2 - dev: true /is-weakset@2.0.2: resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} @@ -3901,7 +4072,6 @@ packages: engines: {node: '>=8'} dependencies: is-docker: 2.2.1 - dev: true /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} @@ -3981,7 +4151,6 @@ packages: /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true /json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} @@ -3993,7 +4162,6 @@ packages: /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true /json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} @@ -4005,7 +4173,6 @@ packages: hasBin: true dependencies: minimist: 1.2.8 - dev: true /json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} @@ -4065,7 +4232,6 @@ packages: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - dev: true /lib-esm@0.4.1: resolution: {integrity: sha512-tdSqfyryhnl5k09357x2iWmw3WeU84SaoP/vMGw/nw8z8RPTrfu9sxwRApn6p6GyStuBNyASgwXIV8ctZWlG1A==} @@ -4094,7 +4260,6 @@ packages: engines: {node: '>=10'} dependencies: p-locate: 5.0.0 - dev: true /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -4110,7 +4275,6 @@ packages: /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -4207,12 +4371,10 @@ packages: /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - dev: true /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} @@ -4220,12 +4382,23 @@ packages: dependencies: braces: 3.0.2 picomatch: 2.3.1 - dev: true + + /mime-db@1.33.0: + resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==} + engines: {node: '>= 0.6'} + dev: false /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + /mime-types@2.1.18: + resolution: {integrity: sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.33.0 + dev: false + /mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} @@ -4269,7 +4442,6 @@ packages: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - dev: true /minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} @@ -4278,6 +4450,13 @@ packages: brace-expansion: 2.0.1 dev: true + /minimatch@7.4.6: + resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: false + /minimatch@9.0.3: resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} @@ -4295,7 +4474,6 @@ packages: /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true /minipass-collect@1.0.2: resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} @@ -4364,12 +4542,26 @@ packages: engines: {node: '>=10'} hasBin: true + /mkdirp@2.1.6: + resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /mrmime@1.0.1: + resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} + engines: {node: '>=10'} + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true /nan@2.18.0: resolution: {integrity: sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==} @@ -4385,7 +4577,6 @@ packages: /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true /negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} @@ -4476,7 +4667,6 @@ packages: engines: {node: '>=8'} dependencies: path-key: 3.1.1 - dev: true /npm-run-path@5.1.0: resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} @@ -4522,7 +4712,6 @@ packages: call-bind: 1.0.2 define-properties: 1.2.1 es-abstract: 1.22.2 - dev: true /object.groupby@1.0.1: resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} @@ -4531,7 +4720,6 @@ packages: define-properties: 1.2.1 es-abstract: 1.22.2 get-intrinsic: 1.2.1 - dev: true /object.values@1.1.7: resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} @@ -4540,7 +4728,11 @@ packages: call-bind: 1.0.2 define-properties: 1.2.1 es-abstract: 1.22.2 - dev: true + + /on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + dev: false /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -4580,7 +4772,6 @@ packages: levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 - dev: true /os-homedir@1.0.2: resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} @@ -4603,7 +4794,6 @@ packages: engines: {node: '>=10'} dependencies: yocto-queue: 0.1.0 - dev: true /p-locate@3.0.0: resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} @@ -4617,7 +4807,6 @@ packages: engines: {node: '>=10'} dependencies: p-limit: 3.1.0 - dev: true /p-map@4.0.0: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} @@ -4646,7 +4835,6 @@ packages: engines: {node: '>=6'} dependencies: callsites: 3.1.0 - dev: true /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} @@ -4665,6 +4853,10 @@ packages: peberminta: 0.9.0 dev: false + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: false + /path-exists@3.0.0: resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} engines: {node: '>=4'} @@ -4673,12 +4865,14 @@ packages: /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - dev: true /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - dev: true + + /path-is-inside@1.0.2: + resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==} + dev: false /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} @@ -4691,7 +4885,6 @@ packages: /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true /path-scurry@1.10.1: resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} @@ -4700,10 +4893,13 @@ packages: lru-cache: 10.0.1 minipass: 7.0.4 + /path-to-regexp@2.2.1: + resolution: {integrity: sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==} + dev: false + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true /pause-stream@0.0.11: resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} @@ -4725,7 +4921,6 @@ packages: /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - dev: true /pkg-up@3.1.0: resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} @@ -4771,7 +4966,6 @@ packages: /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - dev: true /prettier-linter-helpers@1.0.0: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} @@ -4815,18 +5009,36 @@ packages: end-of-stream: 1.4.4 once: 1.4.0 + /punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + dev: false + /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true /quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} + /range-parser@1.2.0: + resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==} + engines: {node: '>= 0.6'} + dev: false + + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: false + /read-config-file@6.3.2: resolution: {integrity: sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==} engines: {node: '>=12.0.0'} @@ -4894,6 +5106,20 @@ packages: define-properties: 1.2.1 set-function-name: 2.0.1 + /registry-auth-token@3.3.2: + resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==} + dependencies: + rc: 1.2.8 + safe-buffer: 5.2.1 + dev: false + + /registry-url@3.1.0: + resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==} + engines: {node: '>=0.10.0'} + dependencies: + rc: 1.2.8 + dev: false + /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -4910,7 +5136,9 @@ packages: /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: true + + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} /resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} @@ -4919,7 +5147,6 @@ packages: is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: true /responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} @@ -4933,14 +5160,12 @@ packages: /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true dependencies: glob: 7.2.3 - dev: true /roarr@2.15.4: resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} @@ -4986,7 +5211,6 @@ packages: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 - dev: true /safe-array-concat@1.0.1: resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} @@ -4996,11 +5220,9 @@ packages: get-intrinsic: 1.2.1 has-symbols: 1.0.3 isarray: 2.0.5 - dev: true /safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -5012,7 +5234,6 @@ packages: call-bind: 1.0.2 get-intrinsic: 1.2.1 is-regex: 1.1.4 - dev: true /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -5068,6 +5289,39 @@ packages: type-fest: 0.20.2 dev: false + /serve-handler@6.1.5: + resolution: {integrity: sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==} + dependencies: + bytes: 3.0.0 + content-disposition: 0.5.2 + fast-url-parser: 1.1.3 + mime-types: 2.1.18 + minimatch: 3.1.2 + path-is-inside: 1.0.2 + path-to-regexp: 2.2.1 + range-parser: 1.2.0 + dev: false + + /serve@14.2.1: + resolution: {integrity: sha512-48er5fzHh7GCShLnNyPBRPEjs2I6QBozeGr02gaacROiyS/8ARADlj595j39iZXAqBbJHH/ivJJyPRWY9sQWZA==} + engines: {node: '>= 14'} + hasBin: true + dependencies: + '@zeit/schemas': 2.29.0 + ajv: 8.11.0 + arg: 5.0.2 + boxen: 7.0.0 + chalk: 5.0.1 + chalk-template: 0.4.0 + clipboardy: 3.0.0 + compression: 1.7.4 + is-port-reachable: 4.0.0 + serve-handler: 6.1.5 + update-check: 1.5.4 + transitivePeerDependencies: + - supports-color + dev: false + /set-function-name@2.0.1: resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} engines: {node: '>= 0.4'} @@ -5099,7 +5353,6 @@ packages: /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} @@ -5112,10 +5365,18 @@ packages: semver: 7.5.4 dev: true + /sirv@2.0.3: + resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==} + engines: {node: '>= 10'} + dependencies: + '@polka/url': 1.0.0-next.23 + mrmime: 1.0.1 + totalist: 3.0.1 + dev: true + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - dev: true /slash@4.0.0: resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} @@ -5249,7 +5510,6 @@ packages: call-bind: 1.0.2 define-properties: 1.2.1 es-abstract: 1.22.2 - dev: true /string.prototype.trimend@1.0.7: resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} @@ -5257,7 +5517,6 @@ packages: call-bind: 1.0.2 define-properties: 1.2.1 es-abstract: 1.22.2 - dev: true /string.prototype.trimstart@1.0.7: resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} @@ -5265,7 +5524,6 @@ packages: call-bind: 1.0.2 define-properties: 1.2.1 es-abstract: 1.22.2 - dev: true /string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -5288,12 +5546,10 @@ packages: /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - dev: true /strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} - dev: true /strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} @@ -5307,10 +5563,14 @@ packages: min-indent: 1.0.1 dev: true + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: false + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - dev: true /sumchecker@3.0.1: resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} @@ -5332,12 +5592,10 @@ packages: engines: {node: '>=8'} dependencies: has-flag: 4.0.0 - dev: true /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - dev: true /synckit@0.8.5: resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} @@ -5347,6 +5605,10 @@ packages: tslib: 2.6.2 dev: true + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + /tar@6.2.0: resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} engines: {node: '>=10'} @@ -5367,7 +5629,6 @@ packages: /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -5415,6 +5676,10 @@ packages: engines: {node: '>=8.0'} dependencies: is-number: 7.0.0 + + /totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} dev: true /trim-newlines@4.1.1: @@ -5435,7 +5700,13 @@ packages: typescript: '>=4.2.0' dependencies: typescript: 5.2.2 - dev: true + + /ts-morph@20.0.0: + resolution: {integrity: sha512-JVmEJy2Wow5n/84I3igthL9sudQ8qzjh/6i4tmYCm6IqYyKFlNbJZi7oBdjyqcWSWYRu3CtL0xbT6fS03ESZIg==} + dependencies: + '@ts-morph/common': 0.21.0 + code-block-writer: 12.0.0 + dev: false /tsconfig-paths@3.14.2: resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} @@ -5444,7 +5715,6 @@ packages: json5: 1.0.2 minimist: 1.2.8 strip-bom: 3.0.0 - dev: true /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -5454,7 +5724,6 @@ packages: engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.2.1 - dev: true /type-fest@0.13.1: resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} @@ -5483,7 +5752,6 @@ packages: call-bind: 1.0.2 get-intrinsic: 1.2.1 is-typed-array: 1.1.12 - dev: true /typed-array-byte-length@1.0.0: resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} @@ -5493,7 +5761,6 @@ packages: for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 - dev: true /typed-array-byte-offset@1.0.0: resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} @@ -5504,7 +5771,6 @@ packages: for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 - dev: true /typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} @@ -5512,7 +5778,6 @@ packages: call-bind: 1.0.2 for-each: 0.3.3 is-typed-array: 1.1.12 - dev: true /typescript@4.9.5: resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} @@ -5524,7 +5789,6 @@ packages: resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} engines: {node: '>=14.17'} hasBin: true - dev: true /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} @@ -5533,7 +5797,6 @@ packages: has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - dev: true /undici-types@5.25.3: resolution: {integrity: sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==} @@ -5590,6 +5853,13 @@ packages: picocolors: 1.0.0 dev: true + /update-check@1.5.4: + resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==} + dependencies: + registry-auth-token: 3.3.2 + registry-url: 3.1.0 + dev: false + /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: @@ -5634,6 +5904,11 @@ packages: spdx-expression-parse: 3.0.1 dev: true + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + /verror@1.10.1: resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} engines: {node: '>=0.6.0'} @@ -5645,13 +5920,37 @@ packages: dev: true optional: true + /vite-plugin-inspect@0.7.42(rollup@4.3.0)(vite@4.5.0): + resolution: {integrity: sha512-JCyX86wr3siQc+p9Kd0t8VkFHAJag0RaQVIpdFGSv5FEaePEVB6+V/RGtz2dQkkGSXQzRWrPs4cU3dRKg32bXw==} + engines: {node: '>=14'} + peerDependencies: + '@nuxt/kit': '*' + vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + dependencies: + '@antfu/utils': 0.7.6 + '@rollup/pluginutils': 5.0.5(rollup@4.3.0) + debug: 4.3.4 + error-stack-parser-es: 0.1.1 + fs-extra: 11.1.1 + open: 9.1.0 + picocolors: 1.0.0 + sirv: 2.0.3 + vite: 4.5.0(@types/node@20.8.6) + transitivePeerDependencies: + - rollup + - supports-color + dev: true + /vite-plugin-resolve@2.5.1: resolution: {integrity: sha512-9dD0Yq5JT1RxHQGZOyhC7e/JlhyhMCftCpQ8TPzQa7KEB/3ERnoCPinH3VJk/0C8qHsA+l41bIcHh5BcHBTmAw==} dependencies: lib-esm: 0.4.1 dev: true - /vite@4.5.0: + /vite@4.5.0(@types/node@20.8.6): resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -5679,6 +5978,7 @@ packages: terser: optional: true dependencies: + '@types/node': 20.8.6 esbuild: 0.18.20 postcss: 8.4.31 rollup: 4.3.0 @@ -5737,6 +6037,13 @@ packages: dependencies: isexe: 3.1.1 + /widest-line@4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + dev: false + /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -5852,7 +6159,6 @@ packages: /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - dev: true /youtubei.js@7.0.0: resolution: {integrity: sha512-z87cv6AAjj0c98BkD0qTJvBDTF2DdT+FntJUjmi+vHY2EV+CepeYQAE/eLsdhGvCb6LrNBgGVwVUzXpHYi8NoA==} diff --git a/src/config/index.ts b/src/config/index.ts index f8bdff14..d9e03365 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -2,8 +2,9 @@ import Store from 'electron-store'; import { deepmerge } from 'deepmerge-ts'; import defaultConfig from './defaults'; -import plugins from './plugins'; + import store from './store'; +import plugins from './plugins'; import { restart } from '../providers/app-controls'; @@ -15,7 +16,7 @@ const setPartial = (key: string, value: object) => { store.set(key, newValue); }; -function setMenuOption(key: string, value: unknown) { +function setMenuOption(key: string, value: unknown) { set(key, value); if (store.get('options.restartOnConfigChanges')) { restart(); @@ -24,24 +25,55 @@ function setMenuOption(key: string, value: unknown) { // MAGIC OF TYPESCRIPT -type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]] -type Join = K extends string | number ? - P extends string | number ? - `${K}${'' extends P ? '' : '.'}${P}` - : never : never; -type Paths = [D] extends [never] ? never : T extends object ? - { [K in keyof T]-?: K extends string | number ? - `${K}` | Join> +type Prev = [ + never, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + ...0[], +]; +type Join = K extends string | number + ? P extends string | number + ? `${K}${'' extends P ? '' : '.'}${P}` : never - }[keyof T] : '' + : never; +type Paths = [D] extends [never] + ? never + : T extends object + ? { + [K in keyof T]-?: K extends string | number + ? `${K}` | Join> + : never; + }[keyof T] + : ''; type SplitKey = K extends `${infer A}.${infer B}` ? [A, B] : [K, string]; -type PathValue = - SplitKey extends [infer A extends keyof T, infer B extends string] - ? PathValue - : T; -const get = >(key: Key) => store.get(key) as PathValue; +type PathValue = SplitKey extends [ + infer A extends keyof T, + infer B extends string, +] + ? PathValue + : T; +const get = >(key: Key) => + store.get(key) as PathValue; export default { defaultConfig, diff --git a/src/config/store.ts b/src/config/store.ts index 80b6c8ff..22f1061b 100644 --- a/src/config/store.ts +++ b/src/config/store.ts @@ -1,15 +1,18 @@ import Store from 'electron-store'; import Conf from 'conf'; -import { pluginBuilders } from 'virtual:PluginBuilders'; +import { allPlugins } from 'virtual:plugins'; import defaults from './defaults'; import { DefaultPresetList, type Preset } from '../plugins/downloader/types'; -const setDefaultPluginOptions = (store: Conf>, plugin: keyof typeof pluginBuilders) => { +const setDefaultPluginOptions = ( + store: Conf>, + plugin: string, +) => { if (!store.get(`plugins.${plugin}`)) { - store.set(`plugins.${plugin}`, pluginBuilders[plugin].config); + store.set(`plugins.${plugin}`, allPlugins[plugin].config); } }; @@ -22,19 +25,24 @@ const migrations = { } }, '>=2.1.0'(store: Conf>) { - const originalPreset = store.get('plugins.downloader.preset') as string | undefined; + const originalPreset = store.get('plugins.downloader.preset') as + | string + | undefined; if (originalPreset) { if (originalPreset !== 'opus') { store.set('plugins.downloader.selectedPreset', 'Custom'); store.set('plugins.downloader.customPresetSetting', { extension: 'mp3', - ffmpegArgs: store.get('plugins.downloader.ffmpegArgs') as string[] ?? DefaultPresetList['mp3 (256kbps)'].ffmpegArgs, + ffmpegArgs: + (store.get('plugins.downloader.ffmpegArgs') as string[]) ?? + DefaultPresetList['mp3 (256kbps)'].ffmpegArgs, } satisfies Preset); } else { store.set('plugins.downloader.selectedPreset', 'Source'); store.set('plugins.downloader.customPresetSetting', { extension: null, - ffmpegArgs: store.get('plugins.downloader.ffmpegArgs') as string[] ?? [], + ffmpegArgs: + (store.get('plugins.downloader.ffmpegArgs') as string[]) ?? [], } satisfies Preset); } store.delete('plugins.downloader.preset'); @@ -47,7 +55,7 @@ const migrations = { if (store.get('plugins.notifications.toastStyle') === undefined) { const pluginOptions = store.get('plugins.notifications') || {}; store.set('plugins.notifications', { - ...pluginBuilders.notifications.config, + ...allPlugins.notifications.config, ...pluginOptions, }); } @@ -82,10 +90,14 @@ const migrations = { } }, '>=1.12.0'(store: Conf>) { - const options = store.get('plugins.shortcuts') as Record>; + const options = store.get('plugins.shortcuts') as Record< + string, + | { + action: string; + shortcut: unknown; + }[] + | Record + >; let updated = false; for (const optionType of ['global', 'local']) { if (Array.isArray(options[optionType])) { @@ -151,12 +163,13 @@ const migrations = { export default new Store({ defaults: { ...defaults, - plugins: Object - .entries(pluginBuilders) - .reduce((prev, [id, builder]) => ({ + plugins: Object.entries(allPlugins).reduce( + (prev, [id, plugin]) => ({ ...prev, - [id]: (builder as PluginBuilderList[keyof PluginBuilderList]).config, - }), {}), + [id]: plugin.config, + }), + {}, + ), }, clearInvalidConfig: false, migrations, diff --git a/src/index.ts b/src/index.ts index e665c975..f4afc0eb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,8 +2,19 @@ import path from 'node:path'; import url from 'node:url'; import fs from 'node:fs'; -import { BrowserWindow, app, screen, globalShortcut, session, shell, dialog, ipcMain } from 'electron'; -import enhanceWebRequest, { BetterSession } from '@jellybrick/electron-better-web-request'; +import { + BrowserWindow, + app, + screen, + globalShortcut, + session, + shell, + dialog, + ipcMain, +} from 'electron'; +import enhanceWebRequest, { + BetterSession, +} from '@jellybrick/electron-better-web-request'; import is from 'electron-is'; import unhandled from 'electron-unhandled'; import { autoUpdater } from 'electron-updater'; @@ -12,30 +23,31 @@ import { parse } from 'node-html-parser'; import { deepmerge } from 'deepmerge-ts'; import { deepEqual } from 'fast-equals'; -import { mainPlugins } from 'virtual:MainPlugins'; -import { pluginBuilders } from 'virtual:PluginBuilders'; +import { mainPlugins } from 'virtual:plugins'; -import config from './config'; +import config from '@/config'; -import { refreshMenu, setApplicationMenu } from './menu'; -import { fileExists, injectCSS, injectCSSAsFile } from './plugins/utils/main'; -import { isTesting } from './utils/testing'; -import { setUpTray } from './tray'; -import { setupSongInfo } from './providers/song-info'; -import { restart, setupAppControls } from './providers/app-controls'; -import { APP_PROTOCOL, handleProtocol, setupProtocolHandler } from './providers/protocol-handler'; +import { refreshMenu, setApplicationMenu } from '@/menu'; +import { fileExists, injectCSS, injectCSSAsFile } from '@/plugins/utils/main'; +import { isTesting } from '@/utils/testing'; +import { setUpTray } from '@/tray'; +import { setupSongInfo } from '@/providers/song-info'; +import { restart, setupAppControls } from '@/providers/app-controls'; +import { + APP_PROTOCOL, + handleProtocol, + setupProtocolHandler, +} from '@/providers/protocol-handler'; - -import youtubeMusicCSS from './youtube-music.css?inline'; +import youtubeMusicCSS from '@/youtube-music.css?inline'; import { forceLoadMainPlugin, forceUnloadMainPlugin, getAllLoadedMainPlugins, loadAllMainPlugins, - registerMainPlugin -} from './loader/main'; -import { MainPluginFactory, PluginBaseConfig, PluginBuilder } from './plugins/utils/builder'; +} from '@/loader/main'; +import { PluginBaseConfig } from '@/plugins/utils/builder'; // Catch errors and log them unhandled({ @@ -57,7 +69,10 @@ if (!gotTheLock) { // SharedArrayBuffer: Required for downloader (@ffmpeg/core-mt) // OverlayScrollbar: Required for overlay scrollbars -app.commandLine.appendSwitch('enable-features', 'OverlayScrollbar,SharedArrayBuffer'); +app.commandLine.appendSwitch( + 'enable-features', + 'OverlayScrollbar,SharedArrayBuffer', +); if (config.get('options.disableHardwareAcceleration')) { if (is.dev()) { console.log('Disabling hardware acceleration'); @@ -95,42 +110,58 @@ function onClosed() { ipcMain.handle('get-main-plugin-names', () => Object.keys(mainPlugins)); - const initHook = (win: BrowserWindow) => { - ipcMain.handle('get-config', (_, id: keyof PluginBuilderList) => deepmerge(pluginBuilders[id].config, config.get(`plugins.${id}`) ?? {}) as PluginBuilderList[typeof id]['config']); - ipcMain.handle('set-config', (_, name: string, obj: object) => config.setPartial(`plugins.${name}`, obj)); + ipcMain.handle( + 'get-config', + (_, id: keyof PluginBuilderList) => + deepmerge( + mainPlugins[id].config, + config.get(`plugins.${id}`) ?? {}, + ) as PluginBuilderList[typeof id]['config'], + ); + ipcMain.handle('set-config', (_, name: string, obj: object) => + config.setPartial(`plugins.${name}`, obj), + ); config.watch((newValue, oldValue) => { - const newPluginConfigList = (newValue?.plugins ?? {}) as Record; - const oldPluginConfigList = (oldValue?.plugins ?? {}) as Record; + const newPluginConfigList = (newValue?.plugins ?? {}) as Record< + string, + unknown + >; + const oldPluginConfigList = (oldValue?.plugins ?? {}) as Record< + string, + unknown + >; Object.entries(newPluginConfigList).forEach(([id, newPluginConfig]) => { const isEqual = deepEqual(oldPluginConfigList[id], newPluginConfig); if (!isEqual) { const oldConfig = oldPluginConfigList[id] as PluginBaseConfig; - const config = deepmerge(pluginBuilders[id as keyof PluginBuilderList].config, newPluginConfig) as PluginBaseConfig; + const config = deepmerge( + mainPlugins[id].config, + newPluginConfig, + ) as PluginBaseConfig; if (config.enabled !== oldConfig?.enabled) { if (config.enabled) { win.webContents.send('plugin:enable', id); ipcMain.emit('plugin:enable', id); - forceLoadMainPlugin(id as keyof PluginBuilderList, win); + forceLoadMainPlugin(id, win); } else { win.webContents.send('plugin:unload', id); ipcMain.emit('plugin:unload', id); - forceUnloadMainPlugin(id as keyof PluginBuilderList, win); + forceUnloadMainPlugin(id, win); } - if (pluginBuilders[id as keyof PluginBuilderList].restartNeeded) { - showNeedToRestartDialog(id as keyof PluginBuilderList); + if (mainPlugins[id].restartNeeded) { + showNeedToRestartDialog(id); } } const mainPlugin = getAllLoadedMainPlugins()[id]; if (mainPlugin) { if (config.enabled) { - mainPlugin.onConfigChange?.(config); } } @@ -140,14 +171,15 @@ const initHook = (win: BrowserWindow) => { }); }; -const showNeedToRestartDialog = (id: keyof PluginBuilderList) => { - const builder = pluginBuilders[id]; +const showNeedToRestartDialog = (id: string) => { + const plugin = mainPlugins[id]; + const dialogOptions: Electron.MessageBoxOptions = { type: 'info', buttons: ['Restart Now', 'Later'], title: 'Restart Required', - message: `"${builder.name ?? builder.id}" needs to restart`, - detail: `"${builder.name ?? builder.id}" plugin requires a restart to take effect`, + message: `"${plugin.name ?? id}" needs to restart`, + detail: `"${plugin.name ?? id}" plugin requires a restart to take effect`, defaultId: 0, cancelId: 1, }; @@ -186,7 +218,10 @@ function initTheme(win: BrowserWindow) { injectCSSAsFile(win.webContents, cssFile); }, () => { - console.warn('[YTMusic]', `CSS file "${cssFile}" does not exist, ignoring`); + console.warn( + '[YTMusic]', + `CSS file "${cssFile}" does not exist, ignoring`, + ); }, ); } @@ -224,46 +259,43 @@ async function createMainWindow() { ...(isTesting() ? undefined : { - // Sandbox is only enabled in tests for now - // See https://www.electronjs.org/docs/latest/tutorial/sandbox#preload-scripts - sandbox: false, - }), + // Sandbox is only enabled in tests for now + // See https://www.electronjs.org/docs/latest/tutorial/sandbox#preload-scripts + sandbox: false, + }), }, frame: !is.macOS() && !useInlineMenu, titleBarOverlay: defaultTitleBarOverlayOptions, titleBarStyle: useInlineMenu ? 'hidden' - : (is.macOS() - ? 'hiddenInset' - : 'default'), + : is.macOS() + ? 'hiddenInset' + : 'default', autoHideMenuBar: config.get('options.hideMenu'), }); initHook(win); initTheme(win); - Object.entries(pluginBuilders).forEach(([id, builder]) => { - const typedBuilder = builder as PluginBuilder; - const plugin = mainPlugins[id] as MainPluginFactory | undefined; - - registerMainPlugin(id, typedBuilder, plugin); - }); await loadAllMainPlugins(win); if (windowPosition) { const { x: windowX, y: windowY } = windowPosition; const winSize = win.getSize(); - const displaySize - = screen.getDisplayNearestPoint(windowPosition).bounds; + const displaySize = screen.getDisplayNearestPoint(windowPosition).bounds; if ( - windowX + winSize[0] < displaySize.x - 8 - || windowX - winSize[0] > displaySize.x + displaySize.width - || windowY < displaySize.y - 8 - || windowY > displaySize.y + displaySize.height + windowX + winSize[0] < displaySize.x - 8 || + windowX - winSize[0] > displaySize.x + displaySize.width || + windowY < displaySize.y - 8 || + windowY > displaySize.y + displaySize.height ) { // Window is offscreen if (is.dev()) { console.log( - `Window tried to render offscreen, windowSize=${String(winSize)}, displaySize=${String(displaySize)}, position=${String(windowPosition)}`, + `Window tried to render offscreen, windowSize=${String( + winSize, + )}, displaySize=${String(displaySize)}, position=${String( + windowPosition, + )}`, ); } } else { @@ -316,7 +348,11 @@ async function createMainWindow() { const savedTimeouts: Record = {}; - function lateSave(key: string, value: unknown, fn: (key: string, value: unknown) => void = config.set) { + function lateSave( + key: string, + value: unknown, + fn: (key: string, value: unknown) => void = config.set, + ) { if (savedTimeouts[key]) { clearTimeout(savedTimeouts[key]); } @@ -343,7 +379,10 @@ async function createMainWindow() { if (useInlineMenu) { win.setTitleBarOverlay({ ...defaultTitleBarOverlayOptions, - height: Math.floor(defaultTitleBarOverlayOptions.height! * win.webContents.getZoomFactor()), + height: Math.floor( + defaultTitleBarOverlayOptions.height! * + win.webContents.getZoomFactor(), + ), }); } @@ -365,14 +404,25 @@ async function createMainWindow() { `); } else { const rendererPath = path.join(__dirname, '..', 'renderer'); - const indexHTML = parse(fs.readFileSync(path.join(rendererPath, 'index.html'), 'utf-8')); + const indexHTML = parse( + fs.readFileSync(path.join(rendererPath, 'index.html'), 'utf-8'), + ); const scriptSrc = indexHTML.querySelector('script')!; - const scriptPath = path.join(rendererPath, scriptSrc.getAttribute('src')!); + const scriptPath = path.join( + rendererPath, + scriptSrc.getAttribute('src')!, + ); const scriptString = fs.readFileSync(scriptPath, 'utf-8'); - await win.webContents.executeJavaScriptInIsolatedWorld(0, [{ - code: scriptString + ';0', - url: url.pathToFileURL(scriptPath).toString(), - }], true); + await win.webContents.executeJavaScriptInIsolatedWorld( + 0, + [ + { + code: scriptString + ';0', + url: url.pathToFileURL(scriptPath).toString(), + }, + ], + true, + ); } }); @@ -387,21 +437,26 @@ app.once('browser-window-created', (event, win) => { const originalUserAgent = win.webContents.userAgent; const userAgents = { mac: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 12.1; rv:95.0) Gecko/20100101 Firefox/95.0', - windows: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0', + windows: + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0', linux: 'Mozilla/5.0 (Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0', }; - const updatedUserAgent - = is.macOS() ? userAgents.mac - : (is.windows() ? userAgents.windows - : userAgents.linux); + const updatedUserAgent = is.macOS() + ? userAgents.mac + : is.windows() + ? userAgents.windows + : userAgents.linux; win.webContents.userAgent = updatedUserAgent; app.userAgentFallback = updatedUserAgent; win.webContents.session.webRequest.onBeforeSendHeaders((details, cb) => { // This will only happen if login failed, and "retry" was pressed - if (win.webContents.getURL().startsWith('https://accounts.google.com') && details.url.startsWith('https://accounts.google.com')) { + if ( + win.webContents.getURL().startsWith('https://accounts.google.com') && + details.url.startsWith('https://accounts.google.com') + ) { details.requestHeaders['User-Agent'] = originalUserAgent; } @@ -412,33 +467,41 @@ app.once('browser-window-created', (event, win) => { setupSongInfo(win); setupAppControls(); - win.webContents.on('did-fail-load', ( - _event, - errorCode, - errorDescription, - validatedURL, - isMainFrame, - frameProcessId, - frameRoutingId, - ) => { - const log = JSON.stringify({ - error: 'did-fail-load', + win.webContents.on( + 'did-fail-load', + ( + _event, errorCode, errorDescription, validatedURL, isMainFrame, frameProcessId, frameRoutingId, - }, null, '\t'); - if (is.dev()) { - console.log(log); - } + ) => { + const log = JSON.stringify( + { + error: 'did-fail-load', + errorCode, + errorDescription, + validatedURL, + isMainFrame, + frameProcessId, + frameRoutingId, + }, + null, + '\t', + ); + if (is.dev()) { + console.log(log); + } - if (errorCode !== -3) { // -3 is a false positive - win.webContents.send('log', log); - win.webContents.loadFile(path.join(__dirname, 'error.html')); - } - }); + if (errorCode !== -3) { + // -3 is a false positive + win.webContents.send('log', log); + win.webContents.loadFile(path.join(__dirname, 'error.html')); + } + }, + ); win.webContents.on('will-prevent-unload', (event) => { event.preventDefault(); @@ -484,17 +547,29 @@ app.on('ready', async () => { const appLocation = process.execPath; const appData = app.getPath('appData'); // Check shortcut validity if not in dev mode / running portable app - if (!is.dev() && !appLocation.startsWith(path.join(appData, '..', 'Local', 'Temp'))) { - const shortcutPath = path.join(appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'YouTube Music.lnk'); - try { // Check if shortcut is registered and valid + if ( + !is.dev() && + !appLocation.startsWith(path.join(appData, '..', 'Local', 'Temp')) + ) { + const shortcutPath = path.join( + appData, + 'Microsoft', + 'Windows', + 'Start Menu', + 'Programs', + 'YouTube Music.lnk', + ); + try { + // Check if shortcut is registered and valid const shortcutDetails = shell.readShortcutLink(shortcutPath); // Throw error if doesn't exist yet if ( - shortcutDetails.target !== appLocation - || shortcutDetails.appUserModelId !== appID + shortcutDetails.target !== appLocation || + shortcutDetails.appUserModelId !== appID ) { throw 'needUpdate'; } - } catch (error) { // If not valid -> Register shortcut + } catch (error) { + // If not valid -> Register shortcut shell.writeShortcutLink( shortcutPath, error === 'needUpdate' ? 'update' : 'create', @@ -556,8 +631,8 @@ app.on('ready', async () => { clearTimeout(updateTimeout); }, 2000); autoUpdater.on('update-available', () => { - const downloadLink - = 'https://github.com/th-ch/youtube-music/releases/latest'; + const downloadLink = + 'https://github.com/th-ch/youtube-music/releases/latest'; const dialogOptions: Electron.MessageBoxOptions = { type: 'info', buttons: ['OK', 'Download', 'Disable updates'], @@ -597,8 +672,10 @@ app.on('ready', async () => { if (config.get('options.hideMenu') && !config.get('options.hideMenuWarned')) { dialog.showMessageBox(mainWindow, { - type: 'info', title: 'Hide Menu Enabled', - message: "Menu is hidden, use 'Alt' to show it (or 'Escape' if using in-app-menu)", + type: 'info', + title: 'Hide Menu Enabled', + message: + "Menu is hidden, use 'Alt' to show it (or 'Escape' if using in-app-menu)", }); config.set('options.hideMenuWarned', true); } @@ -624,31 +701,36 @@ app.on('ready', async () => { } }); -function showUnresponsiveDialog(win: BrowserWindow, details: Electron.RenderProcessGoneDetails) { +function showUnresponsiveDialog( + win: BrowserWindow, + details: Electron.RenderProcessGoneDetails, +) { if (details) { console.log('Unresponsive Error!\n' + JSON.stringify(details, null, '\t')); } - dialog.showMessageBox(win, { - type: 'error', - title: 'Window Unresponsive', - message: 'The Application is Unresponsive', - detail: 'We are sorry for the inconvenience! please choose what to do:', - buttons: ['Wait', 'Relaunch', 'Quit'], - cancelId: 0, - }).then((result) => { - switch (result.response) { - case 1: { - restart(); - break; - } + dialog + .showMessageBox(win, { + type: 'error', + title: 'Window Unresponsive', + message: 'The Application is Unresponsive', + detail: 'We are sorry for the inconvenience! please choose what to do:', + buttons: ['Wait', 'Relaunch', 'Quit'], + cancelId: 0, + }) + .then((result) => { + switch (result.response) { + case 1: { + restart(); + break; + } - case 2: { - app.quit(); - break; + case 2: { + app.quit(); + break; + } } - } - }); + }); } function removeContentSecurityPolicy( @@ -671,18 +753,21 @@ function removeContentSecurityPolicy( }); // When multiple listeners are defined, apply them all - betterSession.webRequest.setResolver('onHeadersReceived', async (listeners) => { - return listeners.reduce( - async (accumulator, listener) => { - const acc = await accumulator; - if (acc.cancel) { - return acc; - } + betterSession.webRequest.setResolver( + 'onHeadersReceived', + async (listeners) => { + return listeners.reduce( + async (accumulator, listener) => { + const acc = await accumulator; + if (acc.cancel) { + return acc; + } - const result = await listener.apply(); - return { ...accumulator, ...result }; - }, - Promise.resolve({ cancel: false }), - ); - }); + const result = await listener.apply(); + return { ...accumulator, ...result }; + }, + Promise.resolve({ cancel: false }), + ); + }, + ); } diff --git a/src/loader/main.ts b/src/loader/main.ts index 883feead..9064a98e 100644 --- a/src/loader/main.ts +++ b/src/loader/main.ts @@ -1,27 +1,24 @@ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-return */ import { BrowserWindow, ipcMain } from 'electron'; import { deepmerge } from 'deepmerge-ts'; +import { mainPlugins } from 'virtual:plugins'; -import config from '../config'; -import { injectCSS } from '../plugins/utils/main'; -import { - MainPlugin, - MainPluginContext, - MainPluginFactory, - PluginBaseConfig, - PluginBuilder -} from '../plugins/utils/builder'; +import { PluginDef } from '@/types/plugins'; +import { BackendContext } from '@/types/contexts'; +import config from '@/config'; +import { startPlugin, stopPlugin } from '@/utils'; -const allPluginFactoryList: Record> = {}; -const allPluginBuilders: Record> = {}; -const unregisterStyleMap: Record void)[]> = {}; -const loadedPluginMap: Record> = {}; +const loadedPluginMap: Record = {}; -const createContext = < - Key extends keyof PluginBuilderList, - Config extends PluginBaseConfig = PluginBuilderList[Key]['config'], ->(id: Key, win: BrowserWindow): MainPluginContext => ({ - getConfig: () => deepmerge(allPluginBuilders[id].config, config.get(`plugins.${id}`) ?? {}) as Config, +const createContext = (id: string, win: BrowserWindow): BackendContext => ({ + getConfig: () => + // @ts-expect-error ts dum dum + deepmerge( + mainPlugins[id].config, + config.get(`plugins.${id}`) ?? { enabled: false }, + ), setConfig: (newConfig) => { config.setPartial(`plugins.${id}`, newConfig); }, @@ -29,81 +26,95 @@ const createContext = < send: (event: string, ...args: unknown[]) => { win.webContents.send(event, ...args); }, + // @ts-expect-error ts dum dum handle: (event: string, listener) => { - ipcMain.handle(event, async (_, ...args) => listener(...args as never)); + // @ts-expect-error ts dum dum + ipcMain.handle(event, (_, ...args) => listener(...(args as never))); }, + // @ts-expect-error ts dum dum on: (event: string, listener) => { - ipcMain.on(event, async (_, ...args) => listener(...args as never)); + // @ts-expect-error ts dum dum + ipcMain.on(event, (_, ...args) => listener(...(args as never))); }, }); -export const forceUnloadMainPlugin = (id: keyof PluginBuilderList, win: BrowserWindow) => { - unregisterStyleMap[id]?.forEach((unregister) => unregister()); - delete unregisterStyleMap[id]; +export const forceUnloadMainPlugin = async ( + id: string, + win: BrowserWindow, +): Promise => { + const plugin = loadedPluginMap[id]!; + if (!plugin) return; - loadedPluginMap[id]?.onUnload?.(win); - delete loadedPluginMap[id]; + return new Promise((resolve, reject) => { + try { + const hasStopped = stopPlugin(id, plugin, { + ctx: 'backend', + context: createContext(id, win), + }); + if (!hasStopped) { + console.log( + '[YTMusic]', + `Cannot unload "${id}" plugin: no stop function`, + ); + reject(); + return; + } - console.log('[YTMusic]', `"${id}" plugin is unloaded`); + delete loadedPluginMap[id]; + console.log('[YTMusic]', `"${id}" plugin is unloaded`); + resolve(); + } catch (err) { + console.log('[YTMusic]', `Cannot unload "${id}" plugin: ${String(err)}`); + reject(err); + } + }); }; -export const forceLoadMainPlugin = async (id: keyof PluginBuilderList, win: BrowserWindow) => { - const builder = allPluginBuilders[id]; +export const forceLoadMainPlugin = async ( + id: string, + win: BrowserWindow, +): Promise => { + const plugin = mainPlugins[id]; + if (!plugin.backend) return; - Promise.allSettled( - builder.styles?.map(async (style) => { - const unregister = await injectCSS(win.webContents, style); - console.log('[YTMusic]', `Injected CSS for "${id}" plugin`); - - return unregister; - }) ?? [], - ).then((result) => { - unregisterStyleMap[id] = result - .map((it) => it.status === 'fulfilled' && it.value) - .filter(Boolean); - - let isInjectSuccess = true; - result.forEach((it) => { - if (it.status === 'rejected') { - isInjectSuccess = false; - - console.log('[YTMusic]', `Cannot inject "${id}" plugin style: ${String(it.reason)}`); + return new Promise((resolve, reject) => { + try { + const hasStarted = startPlugin(id, plugin, { + ctx: 'backend', + context: createContext(id, win), + }); + if (!hasStarted) { + console.log('[YTMusic]', `Cannot load "${id}" plugin`); + reject(); + return; } - }); - if (isInjectSuccess) console.log('[YTMusic]', `"${id}" plugin data is loaded`); + + loadedPluginMap[id] = plugin; + resolve(); + } catch (err) { + console.log( + '[YTMusic]', + `Cannot initialize "${id}" plugin: ${String(err)}`, + ); + reject(err); + } }); - - try { - const factory = allPluginFactoryList[id]; - if (!factory) return; - - const context = createContext(id, win); - const plugin = await factory(context); - loadedPluginMap[id] = plugin; - plugin.onLoad?.(win); - - console.log('[YTMusic]', `"${id}" plugin is loaded`); - } catch (err) { - console.log('[YTMusic]', `Cannot initialize "${id}" plugin: ${String(err)}`); - } }; export const loadAllMainPlugins = async (win: BrowserWindow) => { const pluginConfigs = config.plugins.getPlugins(); + const queue: Promise[] = []; - for (const [pluginId, builder] of Object.entries(allPluginBuilders)) { - const typedBuilder = builder as PluginBuilderList[keyof PluginBuilderList]; - - const config = deepmerge(typedBuilder.config, pluginConfigs[pluginId as keyof PluginBuilderList] ?? {}); - + for (const [plugin, pluginDef] of Object.entries(mainPlugins)) { + const config = deepmerge(pluginDef.config, pluginConfigs[plugin] ?? {}); if (config.enabled) { - await forceLoadMainPlugin(pluginId as keyof PluginBuilderList, win); - } else { - if (loadedPluginMap[pluginId as keyof PluginBuilderList]) { - forceUnloadMainPlugin(pluginId as keyof PluginBuilderList, win); - } + queue.push(forceLoadMainPlugin(plugin, win)); + } else if (loadedPluginMap[plugin]) { + queue.push(forceUnloadMainPlugin(plugin, win)); } } + + await Promise.all(queue); }; export const unloadAllMainPlugins = (win: BrowserWindow) => { @@ -112,17 +123,10 @@ export const unloadAllMainPlugins = (win: BrowserWindow) => { } }; -export const getLoadedMainPlugin = (id: Key): MainPlugin | undefined => { +export const getLoadedMainPlugin = (id: string): PluginDef | undefined => { return loadedPluginMap[id]; }; + export const getAllLoadedMainPlugins = () => { return loadedPluginMap; }; -export const registerMainPlugin = ( - id: string, - builder: PluginBuilder, - factory?: MainPluginFactory, -) => { - if (factory) allPluginFactoryList[id] = factory; - allPluginBuilders[id] = builder; -}; diff --git a/src/loader/menu.ts b/src/loader/menu.ts index 901cfc85..c5717787 100644 --- a/src/loader/menu.ts +++ b/src/loader/menu.ts @@ -1,26 +1,21 @@ import { deepmerge } from 'deepmerge-ts'; +import { allPlugins } from 'virtual:plugins'; +import { BrowserWindow, MenuItemConstructorOptions } from 'electron'; -import { MenuPluginContext, MenuPluginFactory, PluginBaseConfig, PluginBuilder } from '../plugins/utils/builder'; -import config from '../config'; -import { setApplicationMenu } from '../menu'; +import { MenuContext } from '@/types/contexts'; -import type { BrowserWindow, MenuItemConstructorOptions } from 'electron'; +import config from '@/config'; +import { setApplicationMenu } from '@/menu'; -const allPluginFactoryList: Record> = {}; -const allPluginBuilders: Record> = {}; const menuTemplateMap: Record = {}; - -const createContext = < - Key extends keyof PluginBuilderList, - Config extends PluginBaseConfig = PluginBuilderList[Key]['config'], ->(id: Key, win: BrowserWindow): MenuPluginContext => ({ - getConfig: () => deepmerge(allPluginBuilders[id].config, config.get(`plugins.${id}`) ?? {}) as Config, +const createContext = (id: string, win: BrowserWindow): MenuContext => ({ + getConfig: () => config.plugins.getOptions(id), setConfig: (newConfig) => { config.setPartial(`plugins.${id}`, newConfig); }, window: win, - refresh: async () => { - await setApplicationMenu(win); + refresh: () => { + setApplicationMenu(win); if (config.plugins.isEnabled('in-app-menu')) { win.webContents.send('refresh-in-app-menu'); @@ -28,45 +23,39 @@ const createContext = < }, }); -export const forceLoadMenuPlugin = async (id: keyof PluginBuilderList, win: BrowserWindow) => { +export const forceLoadMenuPlugin = (id: string, win: BrowserWindow) => { try { - const factory = allPluginFactoryList[id]; - if (!factory) return; + const plugin = allPlugins[id]; + if (!plugin) return; - const context = createContext(id, win); - menuTemplateMap[id] = await factory(context); + const menu = plugin.menu?.(createContext(id, win)); + if (menu) menuTemplateMap[id] = menu; + else return; - console.log('[YTMusic]', `"${id}" plugin is loaded`); + console.log('[YTMusic]', `Successfully loaded '${id}::menu'`); } catch (err) { - console.log('[YTMusic]', `Cannot initialize "${id}" plugin: ${String(err)}`); + console.log('[YTMusic]', `Cannot initialize '${id}::menu': ${String(err)}`); } }; -export const loadAllMenuPlugins = async (win: BrowserWindow) => { +export const loadAllMenuPlugins = (win: BrowserWindow) => { const pluginConfigs = config.plugins.getPlugins(); - for (const [pluginId, builder] of Object.entries(allPluginBuilders)) { - const typedBuilder = builder as PluginBuilderList[keyof PluginBuilderList]; - - const config = deepmerge(typedBuilder.config, pluginConfigs[pluginId as keyof PluginBuilderList] ?? {}); + for (const [pluginId, pluginDef] of Object.entries(allPlugins)) { + const config = deepmerge(pluginDef.config, pluginConfigs[pluginId] ?? {}); if (config.enabled) { - await forceLoadMenuPlugin(pluginId as keyof PluginBuilderList, win); + forceLoadMenuPlugin(pluginId, win); } } }; -export const getMenuTemplate = (id: Key): MenuItemConstructorOptions[] | undefined => { +export const getMenuTemplate = ( + id: string, +): MenuItemConstructorOptions[] | undefined => { return menuTemplateMap[id]; }; + export const getAllMenuTemplate = () => { return menuTemplateMap; }; -export const registerMenuPlugin = ( - id: string, - builder: PluginBuilder, - factory?: MenuPluginFactory, -) => { - if (factory) allPluginFactoryList[id] = factory; - allPluginBuilders[id] = builder; -}; diff --git a/src/loader/preload.ts b/src/loader/preload.ts index dc598a1e..3fb2287a 100644 --- a/src/loader/preload.ts +++ b/src/loader/preload.ts @@ -1,68 +1,64 @@ import { deepmerge } from 'deepmerge-ts'; +import { preloadPlugins } from 'virtual:plugins'; -import { - PluginBaseConfig, - PluginBuilder, - PreloadPlugin, - PluginContext, - PreloadPluginFactory -} from '../plugins/utils/builder'; -import config from '../config'; +import { type PluginDef } from '@/types/plugins'; +import { type PreloadContext } from '@/types/contexts'; +import { startPlugin, stopPlugin } from '@/utils'; -const allPluginFactoryList: Record> = {}; -const allPluginBuilders: Record> = {}; -const unregisterStyleMap: Record void)[]> = {}; -const loadedPluginMap: Record> = {}; +import config from '@/config'; -const createContext = < - Key extends keyof PluginBuilderList, - Config extends PluginBaseConfig = PluginBuilderList[Key]['config'], ->(id: Key): PluginContext => ({ - getConfig: () => deepmerge(allPluginBuilders[id].config, config.get(`plugins.${id}`) ?? {}) as Config, +const loadedPluginMap: Record = {}; +const createContext = (id: string): PreloadContext => ({ + getConfig: () => config.plugins.getOptions(id), setConfig: (newConfig) => { config.setPartial(`plugins.${id}`, newConfig); }, }); -export const forceUnloadPreloadPlugin = (id: keyof PluginBuilderList) => { - unregisterStyleMap[id]?.forEach((unregister) => unregister()); - delete unregisterStyleMap[id]; - - loadedPluginMap[id]?.onUnload?.(); - delete loadedPluginMap[id]; - +export const forceUnloadPreloadPlugin = (id: string) => { + const hasStopped = stopPlugin(id, loadedPluginMap[id], { + ctx: 'preload', + context: createContext(id), + }); + if (!hasStopped) { + console.log('[YTMusic]', `Cannot stop "${id}" plugin`); + return; + } console.log('[YTMusic]', `"${id}" plugin is unloaded`); }; -export const forceLoadPreloadPlugin = async (id: keyof PluginBuilderList) => { +export const forceLoadPreloadPlugin = (id: string) => { try { - const factory = allPluginFactoryList[id]; - if (!factory) return; + const plugin = preloadPlugins[id]; + if (!plugin) return; - const context = createContext(id); - const plugin = await factory(context); - loadedPluginMap[id] = plugin; - plugin.onLoad?.(); + const hasStarted = startPlugin(id, plugin, { + ctx: 'preload', + context: createContext(id), + }); + + if (hasStarted) loadedPluginMap[id] = plugin; console.log('[YTMusic]', `"${id}" plugin is loaded`); } catch (err) { - console.log('[YTMusic]', `Cannot initialize "${id}" plugin: ${String(err)}`); + console.log( + '[YTMusic]', + `Cannot initialize "${id}" plugin: ${String(err)}`, + ); } }; -export const loadAllPreloadPlugins = async () => { +export const loadAllPreloadPlugins = () => { const pluginConfigs = config.plugins.getPlugins(); - for (const [pluginId, builder] of Object.entries(allPluginBuilders)) { - const typedBuilder = builder as PluginBuilderList[keyof PluginBuilderList]; - - const config = deepmerge(typedBuilder.config, pluginConfigs[pluginId as keyof PluginBuilderList] ?? {}); + for (const [pluginId, pluginDef] of Object.entries(preloadPlugins)) { + const config = deepmerge(pluginDef.config, pluginConfigs[pluginId] ?? {}); if (config.enabled) { - await forceLoadPreloadPlugin(pluginId as keyof PluginBuilderList); + forceLoadPreloadPlugin(pluginId); } else { - if (loadedPluginMap[pluginId as keyof PluginBuilderList]) { - forceUnloadPreloadPlugin(pluginId as keyof PluginBuilderList); + if (loadedPluginMap[pluginId]) { + forceUnloadPreloadPlugin(pluginId); } } } @@ -74,17 +70,10 @@ export const unloadAllPreloadPlugins = () => { } }; -export const getLoadedPreloadPlugin = (id: Key): PreloadPlugin | undefined => { +export const getLoadedPreloadPlugin = (id: string): PluginDef | undefined => { return loadedPluginMap[id]; }; + export const getAllLoadedPreloadPlugins = () => { return loadedPluginMap; }; -export const registerPreloadPlugin = ( - id: string, - builder: PluginBuilder, - factory?: PreloadPluginFactory, -) => { - if (factory) allPluginFactoryList[id] = factory; - allPluginBuilders[id] = builder; -}; diff --git a/src/loader/renderer.ts b/src/loader/renderer.ts index d19b3a88..285527ca 100644 --- a/src/loader/renderer.ts +++ b/src/loader/renderer.ts @@ -1,75 +1,75 @@ import { deepmerge } from 'deepmerge-ts'; -import { - PluginBaseConfig, PluginBuilder, - RendererPlugin, - RendererPluginContext, - RendererPluginFactory -} from '../plugins/utils/builder'; +import { rendererPlugins } from 'virtual:plugins'; + +import { RendererContext } from '@/types/contexts'; + +import { PluginDef } from '@/types/plugins'; +import { startPlugin, stopPlugin } from '@/utils'; -const allPluginFactoryList: Record> = {}; -const allPluginBuilders: Record> = {}; const unregisterStyleMap: Record void)[]> = {}; -const loadedPluginMap: Record> = {}; +const loadedPluginMap: Record = {}; -const createContext = < - Key extends keyof PluginBuilderList, - Config extends PluginBaseConfig = PluginBuilderList[Key]['config'], ->(id: Key): RendererPluginContext => ({ - getConfig: async () => { - return await window.ipcRenderer.invoke('get-config', id) as Config; - }, +const createContext = (id: string): RendererContext => ({ + getConfig: () => window.mainConfig.plugins.getOptions(id), setConfig: async (newConfig) => { await window.ipcRenderer.invoke('set-config', id, newConfig); }, - - invoke: async (event: string, ...args: unknown[]): Promise => { - return await window.ipcRenderer.invoke(event, ...args) as Return; - }, - on: (event: string, listener) => { - window.ipcRenderer.on(event, async (_, ...args) => listener(...args as never)); - }, }); -export const forceUnloadRendererPlugin = (id: keyof PluginBuilderList) => { +export const forceUnloadRendererPlugin = (id: string) => { unregisterStyleMap[id]?.forEach((unregister) => unregister()); - delete unregisterStyleMap[id]; - loadedPluginMap[id]?.onUnload?.(); + delete unregisterStyleMap[id]; delete loadedPluginMap[id]; + const plugin = rendererPlugins[id]; + if (!plugin) return; + + stopPlugin(id, plugin, { ctx: 'renderer', context: createContext(id) }); + if (plugin.renderer?.stylesheet) + document.querySelector(`style#plugin-${id}`)?.remove(); + console.log('[YTMusic]', `"${id}" plugin is unloaded`); }; -export const forceLoadRendererPlugin = async (id: keyof PluginBuilderList) => { - try { - const factory = allPluginFactoryList[id]; - if (!factory) return; +export const forceLoadRendererPlugin = (id: string) => { + const plugin = rendererPlugins[id]; + if (!plugin) return; - const context = createContext(id); - const plugin = await factory(context); + const hasEvaled = startPlugin(id, plugin, { + ctx: 'renderer', + context: createContext(id), + }); + + if (hasEvaled || plugin.renderer?.stylesheet) { loadedPluginMap[id] = plugin; - plugin.onLoad?.(); - console.log('[YTMusic]', `"${id}" plugin is loaded`); - } catch (err) { - console.log('[YTMusic]', `Cannot initialize "${id}" plugin: ${String(err)}`); + if (plugin.renderer?.stylesheet) + document.head.appendChild( + Object.assign(document.createElement('style'), { + id: `plugin-${id}`, + innerHTML: plugin.renderer?.stylesheet ?? '', + }), + ); + + if (!hasEvaled) console.log('[YTMusic]', `"${id}" plugin is loaded`); + } else { + console.log('[YTMusic]', `Cannot initialize "${id}" plugin`); } }; -export const loadAllRendererPlugins = async () => { +export const loadAllRendererPlugins = () => { const pluginConfigs = window.mainConfig.plugins.getPlugins(); - for (const [pluginId, builder] of Object.entries(allPluginBuilders)) { - const typedBuilder = builder as PluginBuilderList[keyof PluginBuilderList]; - - const config = deepmerge(typedBuilder.config, pluginConfigs[pluginId as keyof PluginBuilderList] ?? {}); + for (const [pluginId, pluginDef] of Object.entries(rendererPlugins)) { + const config = deepmerge(pluginDef.config, pluginConfigs[pluginId] ?? {}); if (config.enabled) { - await forceLoadRendererPlugin(pluginId as keyof PluginBuilderList); + forceLoadRendererPlugin(pluginId); } else { - if (loadedPluginMap[pluginId as keyof PluginBuilderList]) { - forceUnloadRendererPlugin(pluginId as keyof PluginBuilderList); + if (loadedPluginMap[pluginId]) { + forceUnloadRendererPlugin(pluginId); } } } @@ -77,21 +77,14 @@ export const loadAllRendererPlugins = async () => { export const unloadAllRendererPlugins = () => { for (const id of Object.keys(loadedPluginMap)) { - forceUnloadRendererPlugin(id as keyof PluginBuilderList); + forceUnloadRendererPlugin(id); } }; -export const getLoadedRendererPlugin = (id: Key): RendererPlugin | undefined => { +export const getLoadedRendererPlugin = (id: string): PluginDef | undefined => { return loadedPluginMap[id]; }; + export const getAllLoadedRendererPlugins = () => { return loadedPluginMap; }; -export const registerRendererPlugin = ( - id: string, - builder: PluginBuilder, - factory?: RendererPluginFactory, -) => { - if (factory) allPluginFactoryList[id] = factory; - allPluginBuilders[id] = builder; -}; diff --git a/src/menu.ts b/src/menu.ts index d8ddb75e..4173052e 100644 --- a/src/menu.ts +++ b/src/menu.ts @@ -1,5 +1,12 @@ import is from 'electron-is'; -import { app, BrowserWindow, clipboard, dialog, Menu } from 'electron'; +import { + app, + BrowserWindow, + clipboard, + dialog, + Menu, + MenuItem, +} from 'electron'; import prompt from 'custom-electron-prompt'; import { restart } from './providers/app-controls'; @@ -8,24 +15,22 @@ import { startingPages } from './providers/extracted-data'; import promptOptions from './providers/prompt-options'; /* eslint-disable import/order */ -import { menuPlugins as menuList } from 'virtual:MenuPlugins'; -import { pluginBuilders } from 'virtual:PluginBuilders'; +import { allPlugins } from 'virtual:plugins'; /* eslint-enable import/order */ -import { getAvailablePluginNames } from './plugins/utils/main'; -import { - MenuPluginFactory, - PluginBaseConfig, - PluginBuilder -} from './plugins/utils/builder'; -import { getAllMenuTemplate, loadAllMenuPlugins, registerMenuPlugin } from './loader/menu'; +import { getAllMenuTemplate, loadAllMenuPlugins } from './loader/menu'; export type MenuTemplate = Electron.MenuItemConstructorOptions[]; // True only if in-app-menu was loaded on launch const inAppMenuActive = config.plugins.isEnabled('in-app-menu'); -const pluginEnabledMenu = (plugin: string, label = '', hasSubmenu = false, refreshMenu: (() => void ) | undefined = undefined): Electron.MenuItemConstructorOptions => ({ +const pluginEnabledMenu = ( + plugin: string, + label = '', + hasSubmenu = false, + refreshMenu: (() => void) | undefined = undefined, +): Electron.MenuItemConstructorOptions => ({ label: label || plugin, type: 'checkbox', checked: config.plugins.isEnabled(plugin), @@ -49,47 +54,42 @@ export const refreshMenu = (win: BrowserWindow) => { } }; -Object.entries(pluginBuilders).forEach(([id, builder]) => { - const typedBuilder = builder as PluginBuilder; - const plugin = menuList[id] as MenuPluginFactory | undefined; - - registerMenuPlugin(id, typedBuilder, plugin); -}); - -export const mainMenuTemplate = async (win: BrowserWindow): Promise => { +export const mainMenuTemplate = (win: BrowserWindow): MenuTemplate => { const innerRefreshMenu = () => refreshMenu(win); - await loadAllMenuPlugins(win); + loadAllMenuPlugins(win); - const menuResult = Object.entries(getAllMenuTemplate()).map(([id, template]) => { - const pluginLabel = (pluginBuilders[id as keyof PluginBuilderList])?.name ?? id; + const menuResult = Object.entries(getAllMenuTemplate()).map( + ([id, template]) => { + const pluginLabel = allPlugins[id]?.name ?? id; + + if (!config.plugins.isEnabled(id)) { + return [ + id, + pluginEnabledMenu(id, pluginLabel, true, innerRefreshMenu), + ] as const; + } - if (!config.plugins.isEnabled(id)) { return [ id, - pluginEnabledMenu(id, pluginLabel, true, innerRefreshMenu), + { + label: pluginLabel, + submenu: [ + pluginEnabledMenu(id, 'Enabled', true, innerRefreshMenu), + { type: 'separator' }, + ...template, + ], + } satisfies Electron.MenuItemConstructorOptions, ] as const; - } + }, + ); - return [ - id, - { - label: pluginLabel, - submenu: [ - pluginEnabledMenu(id, 'Enabled', true, innerRefreshMenu), - { type: 'separator' }, - ...template, - ], - } satisfies Electron.MenuItemConstructorOptions - ] as const; - }); - - const availablePlugins = getAvailablePluginNames(); + const availablePlugins = Object.keys(allPlugins); const pluginMenus = availablePlugins.map((id) => { const predefinedTemplate = menuResult.find((it) => it[0] === id); if (predefinedTemplate) return predefinedTemplate[1]; - const pluginLabel = pluginBuilders[id as keyof PluginBuilderList]?.name ?? id; + const pluginLabel = allPlugins[id]?.name ?? id; return pluginEnabledMenu(id, pluginLabel, true, innerRefreshMenu); }); @@ -106,7 +106,7 @@ export const mainMenuTemplate = async (win: BrowserWindow): Promise { - const subMenuArray: Electron.MenuItemConstructorOptions[] = Object.keys(startingPages).map((name) => ({ - label: name, - type: 'radio', - checked: config.get('options.startingPage') === name, - click() { - config.set('options.startingPage', name); - }, - })); + const subMenuArray: Electron.MenuItemConstructorOptions[] = + Object.keys(startingPages).map((name) => ({ + label: name, + type: 'radio', + checked: config.get('options.startingPage') === name, + click() { + config.set('options.startingPage', name); + }, + })); subMenuArray.unshift({ label: 'Unset', type: 'radio', @@ -147,8 +148,11 @@ export const mainMenuTemplate = async (win: BrowserWindow): Promise