diff --git a/.editorconfig b/.editorconfig index 779f99a1..9d08a1a8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,12 +1,9 @@ root = true [*] -indent_style = space -indent_size = 4 -end_of_line = lf charset = utf-8 -trim_trailing_whitespace = true +indent_style = space +indent_size = 2 +end_of_line = lf insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false +trim_trailing_whitespace = true diff --git a/.erb/configs/.eslintrc b/.erb/configs/.eslintrc deleted file mode 100644 index 89d242ba..00000000 --- a/.erb/configs/.eslintrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "rules": { - "no-console": "off", - "global-require": "off", - "import/no-dynamic-require": "off" - } -} diff --git a/.erb/configs/webpack.config.base.ts b/.erb/configs/webpack.config.base.ts deleted file mode 100644 index c998500c..00000000 --- a/.erb/configs/webpack.config.base.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Base webpack config used across other specific configs - */ - -import webpack from 'webpack'; -import { dependencies as externals } from '../../release/app/package.json'; -import webpackPaths from './webpack.paths'; -import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin'; - -const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default; - -const styledComponentsTransformer = createStyledComponentsTransformer(); - -const configuration: webpack.Configuration = { - externals: [...Object.keys(externals || {})], - - module: { - rules: [ - { - exclude: /node_modules/, - test: /\.[jt]sx?$/, - use: { - loader: 'ts-loader', - options: { - // Remove this line to enable type checking in webpack builds - transpileOnly: true, - getCustomTransformers: () => ({ before: [styledComponentsTransformer] }), - }, - }, - }, - ], - }, - - output: { - // https://github.com/webpack/webpack/issues/1114 - library: { - type: 'commonjs2', - }, - - path: webpackPaths.srcPath, - }, - - plugins: [ - new webpack.EnvironmentPlugin({ - NODE_ENV: 'production', - }), - ], - - /** - * Determine the array of extensions that should be used to resolve modules. - */ - resolve: { - extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'], - fallback: { - child_process: false, - }, - plugins: [new TsconfigPathsPlugin({ baseUrl: webpackPaths.srcPath })], - modules: [webpackPaths.srcPath, 'node_modules'], - }, - - stats: 'errors-only', -}; - -export default configuration; diff --git a/.erb/configs/webpack.config.eslint.ts b/.erb/configs/webpack.config.eslint.ts deleted file mode 100644 index 35a631b7..00000000 --- a/.erb/configs/webpack.config.eslint.ts +++ /dev/null @@ -1,3 +0,0 @@ -/* eslint import/no-unresolved: off, import/no-self-import: off */ - -module.exports = require('./webpack.config.renderer.dev').default; diff --git a/.erb/configs/webpack.config.main.prod.ts b/.erb/configs/webpack.config.main.prod.ts deleted file mode 100644 index 10d1ea17..00000000 --- a/.erb/configs/webpack.config.main.prod.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Webpack config for production electron main process - */ - -import path from 'path'; - -import TerserPlugin from 'terser-webpack-plugin'; -import webpack from 'webpack'; -import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; -import { merge } from 'webpack-merge'; - -import checkNodeEnv from '../scripts/check-node-env'; -import deleteSourceMaps from '../scripts/delete-source-maps'; -import baseConfig from './webpack.config.base'; -import webpackPaths from './webpack.paths'; - -checkNodeEnv('production'); -deleteSourceMaps(); - -const devtoolsConfig = - process.env.DEBUG_PROD === 'true' - ? { - devtool: 'source-map', - } - : {}; - -const configuration: webpack.Configuration = { - ...devtoolsConfig, - - mode: 'production', - - target: 'electron-main', - - entry: { - main: path.join(webpackPaths.srcMainPath, 'main.ts'), - preload: path.join(webpackPaths.srcMainPath, 'preload.ts'), - }, - - output: { - path: webpackPaths.distMainPath, - filename: '[name].js', - }, - - optimization: { - minimizer: [ - new TerserPlugin({ - parallel: true, - }), - ], - }, - - plugins: [ - new BundleAnalyzerPlugin({ - analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled', - }), - - /** - * Create global constants which can be configured at compile time. - * - * Useful for allowing different behaviour between development builds and - * release builds - * - * NODE_ENV should be production so that modules do not perform certain - * development checks - */ - new webpack.EnvironmentPlugin({ - NODE_ENV: 'production', - DEBUG_PROD: false, - START_MINIMIZED: false, - }), - ], - - /** - * Disables webpack processing of __dirname and __filename. - * If you run the bundle in node.js it falls back to these values of node.js. - * https://github.com/webpack/webpack/issues/2010 - */ - node: { - __dirname: false, - __filename: false, - }, -}; - -export default merge(baseConfig, configuration); diff --git a/.erb/configs/webpack.config.preload.dev.ts b/.erb/configs/webpack.config.preload.dev.ts deleted file mode 100644 index 6abb73f2..00000000 --- a/.erb/configs/webpack.config.preload.dev.ts +++ /dev/null @@ -1,70 +0,0 @@ -import path from 'path'; - -import webpack from 'webpack'; -import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; -import { merge } from 'webpack-merge'; - -import checkNodeEnv from '../scripts/check-node-env'; -import baseConfig from './webpack.config.base'; -import webpackPaths from './webpack.paths'; - -// When an ESLint server is running, we can't set the NODE_ENV so we'll check if it's -// at the dev webpack config is not accidentally run in a production environment -if (process.env.NODE_ENV === 'production') { - checkNodeEnv('development'); -} - -const configuration: webpack.Configuration = { - devtool: 'inline-source-map', - - mode: 'development', - - target: 'electron-preload', - - entry: path.join(webpackPaths.srcMainPath, 'preload.ts'), - - output: { - path: webpackPaths.dllPath, - filename: 'preload.js', - }, - - plugins: [ - new BundleAnalyzerPlugin({ - analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled', - }), - - /** - * Create global constants which can be configured at compile time. - * - * Useful for allowing different behaviour between development builds and - * release builds - * - * NODE_ENV should be production so that modules do not perform certain - * development checks - * - * By default, use 'development' as NODE_ENV. This can be overriden with - * 'staging', for example, by changing the ENV variables in the npm scripts - */ - new webpack.EnvironmentPlugin({ - NODE_ENV: 'development', - }), - - new webpack.LoaderOptionsPlugin({ - debug: true, - }), - ], - - /** - * Disables webpack processing of __dirname and __filename. - * If you run the bundle in node.js it falls back to these values of node.js. - * https://github.com/webpack/webpack/issues/2010 - */ - node: { - __dirname: false, - __filename: false, - }, - - watch: true, -}; - -export default merge(baseConfig, configuration); diff --git a/.erb/configs/webpack.config.remote.dev.ts b/.erb/configs/webpack.config.remote.dev.ts deleted file mode 100644 index 3313095e..00000000 --- a/.erb/configs/webpack.config.remote.dev.ts +++ /dev/null @@ -1,127 +0,0 @@ -import 'webpack-dev-server'; -import path from 'path'; - -import HtmlWebpackPlugin from 'html-webpack-plugin'; -import webpack from 'webpack'; -import { merge } from 'webpack-merge'; - -import checkNodeEnv from '../scripts/check-node-env'; -import baseConfig from './webpack.config.base'; -import webpackPaths from './webpack.paths'; - -const { version } = require('../../package.json'); - -// When an ESLint server is running, we can't set the NODE_ENV so we'll check if it's -// at the dev webpack config is not accidentally run in a production environment -if (process.env.NODE_ENV === 'production') { - checkNodeEnv('development'); -} - -const configuration: webpack.Configuration = { - devtool: 'inline-source-map', - - mode: 'development', - - target: ['web'], - - entry: { - remote: path.join(webpackPaths.srcRemotePath, 'index.tsx'), - worker: path.join(webpackPaths.srcRemotePath, 'service-worker.ts'), - }, - - output: { - path: webpackPaths.dllPath, - publicPath: '/', - filename: '[name].js', - library: { - type: 'umd', - }, - }, - - module: { - rules: [ - { - test: /\.s?css$/, - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - modules: true, - sourceMap: true, - importLoaders: 1, - }, - }, - 'sass-loader', - ], - include: /\.module\.s?(c|a)ss$/, - }, - { - test: /\.s?css$/, - use: ['style-loader', 'css-loader', 'sass-loader'], - exclude: /\.module\.s?(c|a)ss$/, - }, - // Fonts - { - test: /\.(woff|woff2|eot|ttf|otf)$/i, - type: 'asset/resource', - }, - // Images - { - test: /\.(png|svg|jpg|jpeg|gif)$/i, - type: 'asset/resource', - }, - ], - }, - plugins: [ - new webpack.NoEmitOnErrorsPlugin(), - - /** - * Create global constants which can be configured at compile time. - * - * Useful for allowing different behaviour between development builds and - * release builds - * - * NODE_ENV should be production so that modules do not perform certain - * development checks - * - * By default, use 'development' as NODE_ENV. This can be overriden with - * 'staging', for example, by changing the ENV variables in the npm scripts - */ - new webpack.EnvironmentPlugin({ - NODE_ENV: 'development', - }), - - new webpack.LoaderOptionsPlugin({ - debug: true, - }), - - new HtmlWebpackPlugin({ - filename: path.join('index.html'), - template: path.join(webpackPaths.srcRemotePath, 'index.ejs'), - favicon: path.join(webpackPaths.assetsPath, 'icons', 'favicon.ico'), - minify: { - collapseWhitespace: true, - removeAttributeQuotes: true, - removeComments: true, - }, - isBrowser: true, - env: process.env.NODE_ENV, - isDevelopment: process.env.NODE_ENV !== 'production', - nodeModules: webpackPaths.appNodeModulesPath, - templateParameters: { - version, - prod: false, - }, - }), - ], - - node: { - __dirname: false, - __filename: false, - }, - - watch: true, -}; - -export default merge(baseConfig, configuration); diff --git a/.erb/configs/webpack.config.remote.prod.ts b/.erb/configs/webpack.config.remote.prod.ts deleted file mode 100644 index d96dbe5b..00000000 --- a/.erb/configs/webpack.config.remote.prod.ts +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Build config for electron renderer process - */ - -import path from 'path'; - -import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; -import HtmlWebpackPlugin from 'html-webpack-plugin'; -import MiniCssExtractPlugin from 'mini-css-extract-plugin'; -import TerserPlugin from 'terser-webpack-plugin'; -import webpack from 'webpack'; -import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; -import { merge } from 'webpack-merge'; - -import checkNodeEnv from '../scripts/check-node-env'; -import deleteSourceMaps from '../scripts/delete-source-maps'; -import baseConfig from './webpack.config.base'; -import webpackPaths from './webpack.paths'; - -const { version } = require('../../package.json'); - -checkNodeEnv('production'); -deleteSourceMaps(); - -const devtoolsConfig = - process.env.DEBUG_PROD === 'true' - ? { - devtool: 'source-map', - } - : {}; - -const configuration: webpack.Configuration = { - ...devtoolsConfig, - - mode: 'production', - - target: ['web'], - - entry: { - remote: path.join(webpackPaths.srcRemotePath, 'index.tsx'), - worker: path.join(webpackPaths.srcRemotePath, 'service-worker.ts'), - }, - - output: { - path: webpackPaths.distRemotePath, - publicPath: './', - filename: '[name].js', - library: { - type: 'umd', - }, - }, - - module: { - rules: [ - { - test: /\.s?(a|c)ss$/, - use: [ - MiniCssExtractPlugin.loader, - { - loader: 'css-loader', - options: { - modules: true, - sourceMap: true, - importLoaders: 1, - }, - }, - 'sass-loader', - ], - include: /\.module\.s?(c|a)ss$/, - }, - { - test: /\.s?(a|c)ss$/, - use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'], - exclude: /\.module\.s?(c|a)ss$/, - }, - // Fonts - { - test: /\.(woff|woff2|eot|ttf|otf)$/i, - type: 'asset/resource', - }, - // Images - { - test: /\.(png|svg|jpg|jpeg|gif)$/i, - type: 'asset/resource', - }, - ], - }, - - optimization: { - minimize: true, - minimizer: [ - new TerserPlugin({ - parallel: true, - }), - new CssMinimizerPlugin(), - ], - }, - - plugins: [ - /** - * Create global constants which can be configured at compile time. - * - * Useful for allowing different behaviour between development builds and - * release builds - * - * NODE_ENV should be production so that modules do not perform certain - * development checks - */ - new webpack.EnvironmentPlugin({ - NODE_ENV: 'production', - DEBUG_PROD: false, - }), - - new MiniCssExtractPlugin({ - filename: 'remote.css', - }), - - new BundleAnalyzerPlugin({ - analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled', - }), - - new HtmlWebpackPlugin({ - filename: 'index.html', - template: path.join(webpackPaths.srcRemotePath, 'index.ejs'), - favicon: path.join(webpackPaths.assetsPath, 'icons', 'favicon.ico'), - minify: { - collapseWhitespace: true, - removeAttributeQuotes: true, - removeComments: true, - }, - isBrowser: true, - env: process.env.NODE_ENV, - isDevelopment: process.env.NODE_ENV !== 'production', - templateParameters: { - version, - prod: true, - }, - }), - ], -}; - -export default merge(baseConfig, configuration); diff --git a/.erb/configs/webpack.config.renderer.dev.dll.ts b/.erb/configs/webpack.config.renderer.dev.dll.ts deleted file mode 100644 index dea71afb..00000000 --- a/.erb/configs/webpack.config.renderer.dev.dll.ts +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Builds the DLL for development electron renderer process - */ - -import path from 'path'; - -import webpack from 'webpack'; -import { merge } from 'webpack-merge'; - -import { dependencies } from '../../package.json'; -import checkNodeEnv from '../scripts/check-node-env'; -import baseConfig from './webpack.config.base'; -import webpackPaths from './webpack.paths'; - -checkNodeEnv('development'); - -const dist = webpackPaths.dllPath; - -const configuration: webpack.Configuration = { - context: webpackPaths.rootPath, - - devtool: 'eval', - - mode: 'development', - - target: 'electron-renderer', - - externals: ['fsevents', 'crypto-browserify'], - - /** - * Use `module` from `webpack.config.renderer.dev.js` - */ - module: require('./webpack.config.renderer.dev').default.module, - - entry: { - renderer: Object.keys(dependencies || {}), - }, - - output: { - path: dist, - filename: '[name].dev.dll.js', - library: { - name: 'renderer', - type: 'var', - }, - }, - - plugins: [ - new webpack.DllPlugin({ - path: path.join(dist, '[name].json'), - name: '[name]', - }), - - /** - * Create global constants which can be configured at compile time. - * - * Useful for allowing different behaviour between development builds and - * release builds - * - * NODE_ENV should be production so that modules do not perform certain - * development checks - */ - new webpack.EnvironmentPlugin({ - NODE_ENV: 'development', - }), - - new webpack.LoaderOptionsPlugin({ - debug: true, - options: { - context: webpackPaths.srcPath, - output: { - path: webpackPaths.dllPath, - }, - }, - }), - ], -}; - -export default merge(baseConfig, configuration); diff --git a/.erb/configs/webpack.config.renderer.dev.ts b/.erb/configs/webpack.config.renderer.dev.ts deleted file mode 100644 index 46e51530..00000000 --- a/.erb/configs/webpack.config.renderer.dev.ts +++ /dev/null @@ -1,201 +0,0 @@ -import 'webpack-dev-server'; -import { execSync, spawn } from 'child_process'; -import fs from 'fs'; -import path from 'path'; - -import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin'; -import chalk from 'chalk'; -import HtmlWebpackPlugin from 'html-webpack-plugin'; -import webpack from 'webpack'; -import { merge } from 'webpack-merge'; - -import checkNodeEnv from '../scripts/check-node-env'; -import baseConfig from './webpack.config.base'; -import webpackPaths from './webpack.paths'; - -// When an ESLint server is running, we can't set the NODE_ENV so we'll check if it's -// at the dev webpack config is not accidentally run in a production environment -if (process.env.NODE_ENV === 'production') { - checkNodeEnv('development'); -} - -const port = process.env.PORT || 4343; -const manifest = path.resolve(webpackPaths.dllPath, 'renderer.json'); -// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -const requiredByDLLConfig = module.parent!.filename.includes('webpack.config.renderer.dev.dll'); - -/** - * Warn if the DLL is not built - */ -if (!requiredByDLLConfig && !(fs.existsSync(webpackPaths.dllPath) && fs.existsSync(manifest))) { - console.log( - chalk.black.bgYellow.bold( - 'The DLL files are missing. Sit back while we build them for you with "npm run build-dll"', - ), - ); - execSync('npm run postinstall'); -} - -const configuration: webpack.Configuration = { - devtool: 'inline-source-map', - - mode: 'development', - - target: ['web', 'electron-renderer'], - - entry: [ - `webpack-dev-server/client?http://localhost:${port}/dist`, - 'webpack/hot/only-dev-server', - path.join(webpackPaths.srcRendererPath, 'index.tsx'), - ], - - output: { - path: webpackPaths.distRendererPath, - publicPath: '/', - filename: 'renderer.dev.js', - library: { - type: 'umd', - }, - }, - - module: { - rules: [ - { - test: /\.s?css$/, - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - modules: { - localIdentName: '[name]__[local]--[hash:base64:5]', - exportLocalsConvention: 'camelCaseOnly', - }, - sourceMap: true, - importLoaders: 1, - }, - }, - 'sass-loader', - ], - include: /\.module\.s?(c|a)ss$/, - }, - { - test: /\.s?css$/, - use: ['style-loader', 'css-loader', 'sass-loader'], - exclude: /\.module\.s?(c|a)ss$/, - }, - // Fonts - { - test: /\.(woff|woff2|eot|ttf|otf)$/i, - type: 'asset/resource', - }, - // Images - { - test: /\.(png|svg|jpg|jpeg|gif)$/i, - type: 'asset/resource', - }, - ], - }, - plugins: [ - ...(requiredByDLLConfig - ? [] - : [ - new webpack.DllReferencePlugin({ - context: webpackPaths.dllPath, - manifest: require(manifest), - sourceType: 'var', - }), - ]), - - new webpack.NoEmitOnErrorsPlugin(), - - /** - * Create global constants which can be configured at compile time. - * - * Useful for allowing different behaviour between development builds and - * release builds - * - * NODE_ENV should be production so that modules do not perform certain - * development checks - * - * By default, use 'development' as NODE_ENV. This can be overriden with - * 'staging', for example, by changing the ENV variables in the npm scripts - */ - new webpack.EnvironmentPlugin({ - NODE_ENV: 'development', - }), - - new webpack.LoaderOptionsPlugin({ - debug: true, - }), - - new ReactRefreshWebpackPlugin(), - - new HtmlWebpackPlugin({ - filename: path.join('index.html'), - template: path.join(webpackPaths.srcRendererPath, 'index.ejs'), - minify: { - collapseWhitespace: true, - removeAttributeQuotes: true, - removeComments: true, - }, - isBrowser: false, - env: process.env.NODE_ENV, - isDevelopment: process.env.NODE_ENV !== 'production', - nodeModules: webpackPaths.appNodeModulesPath, - templateParameters: { - web: false, - }, - }), - ], - - node: { - __dirname: false, - __filename: false, - }, - - devServer: { - port, - compress: true, - hot: true, - headers: { 'Access-Control-Allow-Origin': '*' }, - static: { - publicPath: '/', - }, - historyApiFallback: { - verbose: true, - }, - setupMiddlewares(middlewares) { - console.log('Starting preload.js builder...'); - const preloadProcess = spawn('npm', ['run', 'start:preload'], { - shell: true, - stdio: 'inherit', - }) - .on('close', (code: number) => process.exit(code!)) - .on('error', (spawnError) => console.error(spawnError)); - - console.log('Starting remote.js builder...'); - const remoteProcess = spawn('npm', ['run', 'start:remote'], { - shell: true, - stdio: 'inherit', - }) - .on('close', (code: number) => process.exit(code!)) - .on('error', (spawnError) => console.error(spawnError)); - - console.log('Starting Main Process...'); - spawn('npm', ['run', 'start:main'], { - shell: true, - stdio: 'inherit', - }) - .on('close', (code: number) => { - preloadProcess.kill(); - remoteProcess.kill(); - process.exit(code!); - }) - .on('error', (spawnError) => console.error(spawnError)); - return middlewares; - }, - }, -}; - -export default merge(baseConfig, configuration); diff --git a/.erb/configs/webpack.config.renderer.prod.ts b/.erb/configs/webpack.config.renderer.prod.ts deleted file mode 100644 index 379bb2d0..00000000 --- a/.erb/configs/webpack.config.renderer.prod.ts +++ /dev/null @@ -1,137 +0,0 @@ -/** - * Build config for electron renderer process - */ - -import path from 'path'; - -import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; -import HtmlWebpackPlugin from 'html-webpack-plugin'; -import MiniCssExtractPlugin from 'mini-css-extract-plugin'; -import TerserPlugin from 'terser-webpack-plugin'; -import webpack from 'webpack'; -import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; -import { merge } from 'webpack-merge'; - -import checkNodeEnv from '../scripts/check-node-env'; -import deleteSourceMaps from '../scripts/delete-source-maps'; -import baseConfig from './webpack.config.base'; -import webpackPaths from './webpack.paths'; - -checkNodeEnv('production'); -deleteSourceMaps(); - -const devtoolsConfig = - process.env.DEBUG_PROD === 'true' - ? { - devtool: 'source-map', - } - : {}; - -const configuration: webpack.Configuration = { - ...devtoolsConfig, - - mode: 'production', - - target: ['web', 'electron-renderer'], - - entry: [path.join(webpackPaths.srcRendererPath, 'index.tsx')], - - output: { - path: webpackPaths.distRendererPath, - publicPath: './', - filename: 'renderer.js', - library: { - type: 'umd', - }, - }, - - module: { - rules: [ - { - test: /\.s?(a|c)ss$/, - use: [ - MiniCssExtractPlugin.loader, - { - loader: 'css-loader', - options: { - modules: { - localIdentName: '[name]__[local]--[hash:base64:5]', - exportLocalsConvention: 'camelCaseOnly', - }, - sourceMap: true, - importLoaders: 1, - }, - }, - 'sass-loader', - ], - include: /\.module\.s?(c|a)ss$/, - }, - { - test: /\.s?(a|c)ss$/, - use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'], - exclude: /\.module\.s?(c|a)ss$/, - }, - // Fonts - { - test: /\.(woff|woff2|eot|ttf|otf)$/i, - type: 'asset/resource', - }, - // Images - { - test: /\.(png|svg|jpg|jpeg|gif)$/i, - type: 'asset/resource', - }, - ], - }, - - optimization: { - minimize: true, - minimizer: [ - new TerserPlugin({ - parallel: true, - }), - new CssMinimizerPlugin(), - ], - }, - - plugins: [ - /** - * Create global constants which can be configured at compile time. - * - * Useful for allowing different behaviour between development builds and - * release builds - * - * NODE_ENV should be production so that modules do not perform certain - * development checks - */ - new webpack.EnvironmentPlugin({ - NODE_ENV: 'production', - DEBUG_PROD: false, - }), - - new MiniCssExtractPlugin({ - filename: 'style.css', - }), - - new BundleAnalyzerPlugin({ - analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled', - }), - - new HtmlWebpackPlugin({ - filename: 'index.html', - template: path.join(webpackPaths.srcRendererPath, 'index.ejs'), - minify: { - collapseWhitespace: true, - removeAttributeQuotes: true, - removeComments: true, - }, - isBrowser: false, - isDevelopment: process.env.NODE_ENV !== 'production', - templateParameters: { - web: false, - }, - }), - ], -}; - -export default merge(baseConfig, configuration); diff --git a/.erb/configs/webpack.config.renderer.web.ts b/.erb/configs/webpack.config.renderer.web.ts deleted file mode 100644 index 82b5f79a..00000000 --- a/.erb/configs/webpack.config.renderer.web.ts +++ /dev/null @@ -1,147 +0,0 @@ -import 'webpack-dev-server'; -import path from 'path'; - -import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin'; -import HtmlWebpackPlugin from 'html-webpack-plugin'; -import webpack from 'webpack'; -import { merge } from 'webpack-merge'; - -import checkNodeEnv from '../scripts/check-node-env'; -import baseConfig from './webpack.config.base'; -import webpackPaths from './webpack.paths'; - -// When an ESLint server is running, we can't set the NODE_ENV so we'll check if it's -// at the dev webpack config is not accidentally run in a production environment -if (process.env.NODE_ENV === 'production') { - checkNodeEnv('development'); -} - -const port = process.env.PORT || 4343; - -const configuration: webpack.Configuration = { - devtool: 'inline-source-map', - - mode: 'development', - - target: ['web', 'electron-renderer'], - - entry: [ - `webpack-dev-server/client?http://localhost:${port}/dist`, - 'webpack/hot/only-dev-server', - path.join(webpackPaths.srcRendererPath, 'index.tsx'), - ], - - output: { - path: webpackPaths.distRendererPath, - publicPath: '/', - filename: 'renderer.dev.js', - library: { - type: 'umd', - }, - }, - - module: { - rules: [ - { - test: /\.s?css$/, - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - modules: { - localIdentName: '[name]__[local]--[hash:base64:5]', - exportLocalsConvention: 'camelCaseOnly', - }, - sourceMap: true, - importLoaders: 1, - }, - }, - 'sass-loader', - ], - include: /\.module\.s?(c|a)ss$/, - }, - { - test: /\.s?css$/, - use: ['style-loader', 'css-loader', 'sass-loader'], - exclude: /\.module\.s?(c|a)ss$/, - }, - // Fonts - { - test: /\.(woff|woff2|eot|ttf|otf)$/i, - type: 'asset/resource', - }, - // Images - { - test: /\.(png|svg|jpg|jpeg|gif)$/i, - type: 'asset/resource', - }, - ], - }, - plugins: [ - new webpack.NoEmitOnErrorsPlugin(), - - /** - * Create global constants which can be configured at compile time. - * - * Useful for allowing different behaviour between development builds and - * release builds - * - * NODE_ENV should be production so that modules do not perform certain - * development checks - * - * By default, use 'development' as NODE_ENV. This can be overriden with - * 'staging', for example, by changing the ENV variables in the npm scripts - */ - new webpack.EnvironmentPlugin({ - NODE_ENV: 'development', - }), - - new webpack.LoaderOptionsPlugin({ - debug: true, - }), - - new ReactRefreshWebpackPlugin(), - - new HtmlWebpackPlugin({ - filename: path.join('index.html'), - template: path.join(webpackPaths.srcRendererPath, 'index.ejs'), - favicon: path.join(webpackPaths.assetsPath, 'icons', 'favicon.ico'), - minify: { - collapseWhitespace: true, - removeAttributeQuotes: true, - removeComments: true, - }, - isBrowser: false, - env: process.env.NODE_ENV, - isDevelopment: process.env.NODE_ENV !== 'production', - nodeModules: webpackPaths.appNodeModulesPath, - templateParameters: { - web: false, // with hot reload, we don't have NGINX injecting variables - }, - }), - ], - - node: { - __dirname: false, - __filename: false, - }, - - devServer: { - port, - compress: true, - hot: true, - headers: { 'Access-Control-Allow-Origin': '*' }, - static: { - publicPath: '/', - }, - historyApiFallback: { - verbose: true, - }, - setupMiddlewares(middlewares) { - return middlewares; - }, - }, -}; - -export default merge(baseConfig, configuration); diff --git a/.erb/configs/webpack.config.web.prod.ts b/.erb/configs/webpack.config.web.prod.ts deleted file mode 100644 index ed935fd6..00000000 --- a/.erb/configs/webpack.config.web.prod.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Build config for electron renderer process - */ - -import path from 'path'; - -import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; -import HtmlWebpackPlugin from 'html-webpack-plugin'; -import MiniCssExtractPlugin from 'mini-css-extract-plugin'; -import TerserPlugin from 'terser-webpack-plugin'; -import webpack from 'webpack'; -import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; -import { merge } from 'webpack-merge'; - -import checkNodeEnv from '../scripts/check-node-env'; -import deleteSourceMaps from '../scripts/delete-source-maps'; -import baseConfig from './webpack.config.base'; -import webpackPaths from './webpack.paths'; - -checkNodeEnv('production'); -deleteSourceMaps(); - -const devtoolsConfig = - process.env.DEBUG_PROD === 'true' - ? { - devtool: 'source-map', - } - : {}; - -const configuration: webpack.Configuration = { - ...devtoolsConfig, - - mode: 'production', - - target: ['web'], - - entry: [path.join(webpackPaths.srcRendererPath, 'index.tsx')], - - output: { - path: webpackPaths.distWebPath, - publicPath: 'auto', - filename: 'renderer.js', - library: { - type: 'umd', - }, - }, - - module: { - rules: [ - { - test: /\.s?(a|c)ss$/, - use: [ - MiniCssExtractPlugin.loader, - { - loader: 'css-loader', - options: { - modules: { - localIdentName: '[name]__[local]--[hash:base64:5]', - exportLocalsConvention: 'camelCaseOnly', - }, - sourceMap: true, - importLoaders: 1, - }, - }, - 'sass-loader', - ], - include: /\.module\.s?(c|a)ss$/, - }, - { - test: /\.s?(a|c)ss$/, - use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'], - exclude: /\.module\.s?(c|a)ss$/, - }, - // Fonts - { - test: /\.(woff|woff2|eot|ttf|otf)$/i, - type: 'asset/resource', - }, - // Images - { - test: /\.(png|svg|jpg|jpeg|gif)$/i, - type: 'asset/resource', - }, - ], - }, - - optimization: { - minimize: true, - minimizer: [ - new TerserPlugin({ - parallel: true, - }), - new CssMinimizerPlugin(), - ], - }, - - plugins: [ - /** - * Create global constants which can be configured at compile time. - * - * Useful for allowing different behaviour between development builds and - * release builds - * - * NODE_ENV should be production so that modules do not perform certain - * development checks - */ - new webpack.EnvironmentPlugin({ - NODE_ENV: 'production', - DEBUG_PROD: false, - }), - - new MiniCssExtractPlugin({ - filename: 'style.css', - }), - - new BundleAnalyzerPlugin({ - analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled', - }), - - new HtmlWebpackPlugin({ - filename: 'index.html', - template: path.join(webpackPaths.srcRendererPath, 'index.ejs'), - favicon: path.join(webpackPaths.assetsPath, 'icons', 'favicon.ico'), - minify: { - collapseWhitespace: true, - removeAttributeQuotes: true, - removeComments: true, - }, - isBrowser: false, - isDevelopment: process.env.NODE_ENV !== 'production', - templateParameters: { - web: true, - }, - }), - ], -}; - -export default merge(baseConfig, configuration); diff --git a/.erb/configs/webpack.paths.ts b/.erb/configs/webpack.paths.ts deleted file mode 100644 index cb1db0cb..00000000 --- a/.erb/configs/webpack.paths.ts +++ /dev/null @@ -1,46 +0,0 @@ -const path = require('path'); - -const rootPath = path.join(__dirname, '../..'); - -const dllPath = path.join(__dirname, '../dll'); - -const srcPath = path.join(rootPath, 'src'); -const assetsPath = path.join(rootPath, 'assets'); -const srcMainPath = path.join(srcPath, 'main'); -const srcRemotePath = path.join(srcPath, 'remote'); -const srcRendererPath = path.join(srcPath, 'renderer'); - -const releasePath = path.join(rootPath, 'release'); -const appPath = path.join(releasePath, 'app'); -const appPackagePath = path.join(appPath, 'package.json'); -const appNodeModulesPath = path.join(appPath, 'node_modules'); -const srcNodeModulesPath = path.join(srcPath, 'node_modules'); - -const distPath = path.join(appPath, 'dist'); -const distMainPath = path.join(distPath, 'main'); -const distRemotePath = path.join(distPath, 'remote'); -const distRendererPath = path.join(distPath, 'renderer'); -const distWebPath = path.join(distPath, 'web'); - -const buildPath = path.join(releasePath, 'build'); - -export default { - assetsPath, - rootPath, - dllPath, - srcPath, - srcMainPath, - srcRemotePath, - srcRendererPath, - releasePath, - appPath, - appPackagePath, - appNodeModulesPath, - srcNodeModulesPath, - distPath, - distMainPath, - distRemotePath, - distRendererPath, - distWebPath, - buildPath, -}; diff --git a/.erb/mocks/fileMock.js b/.erb/mocks/fileMock.js deleted file mode 100644 index 602eb23e..00000000 --- a/.erb/mocks/fileMock.js +++ /dev/null @@ -1 +0,0 @@ -export default 'test-file-stub'; diff --git a/.erb/scripts/.eslintrc b/.erb/scripts/.eslintrc deleted file mode 100644 index 35dc618d..00000000 --- a/.erb/scripts/.eslintrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "rules": { - "no-console": "off", - "global-require": "off", - "import/no-dynamic-require": "off", - "import/no-extraneous-dependencies": "off" - } -} diff --git a/.erb/scripts/check-build-exists.ts b/.erb/scripts/check-build-exists.ts deleted file mode 100644 index 1d299a2f..00000000 --- a/.erb/scripts/check-build-exists.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Check if the renderer and main bundles are built -import path from 'path'; -import chalk from 'chalk'; -import fs from 'fs'; -import webpackPaths from '../configs/webpack.paths'; - -const mainPath = path.join(webpackPaths.distMainPath, 'main.js'); -const remotePath = path.join(webpackPaths.distMainPath, 'remote.js'); -const rendererPath = path.join(webpackPaths.distRendererPath, 'renderer.js'); - -if (!fs.existsSync(mainPath)) { - throw new Error( - chalk.whiteBright.bgRed.bold( - 'The main process is not built yet. Build it by running "npm run build:main"', - ), - ); -} - -if (!fs.existsSync(remotePath)) { - throw new Error( - chalk.whiteBright.bgRed.bold( - 'The remote process is not built yet. Build it by running "npm run build:remote"', - ), - ); -} - -if (!fs.existsSync(rendererPath)) { - throw new Error( - chalk.whiteBright.bgRed.bold( - 'The renderer process is not built yet. Build it by running "npm run build:renderer"', - ), - ); -} diff --git a/.erb/scripts/check-native-dep.js b/.erb/scripts/check-native-dep.js deleted file mode 100644 index f5a23268..00000000 --- a/.erb/scripts/check-native-dep.js +++ /dev/null @@ -1,54 +0,0 @@ -import fs from 'fs'; -import chalk from 'chalk'; -import { execSync } from 'child_process'; -import { dependencies } from '../../package.json'; - -if (dependencies) { - const dependenciesKeys = Object.keys(dependencies); - const nativeDeps = fs - .readdirSync('node_modules') - .filter((folder) => fs.existsSync(`node_modules/${folder}/binding.gyp`)); - if (nativeDeps.length === 0) { - process.exit(0); - } - try { - // Find the reason for why the dependency is installed. If it is installed - // because of a devDependency then that is okay. Warn when it is installed - // because of a dependency - const { dependencies: dependenciesObject } = JSON.parse( - execSync(`npm ls ${nativeDeps.join(' ')} --json`).toString() - ); - const rootDependencies = Object.keys(dependenciesObject); - const filteredRootDependencies = rootDependencies.filter((rootDependency) => - dependenciesKeys.includes(rootDependency) - ); - if (filteredRootDependencies.length > 0) { - const plural = filteredRootDependencies.length > 1; - console.log(` - ${chalk.whiteBright.bgYellow.bold( - 'Webpack does not work with native dependencies.' - )} -${chalk.bold(filteredRootDependencies.join(', '))} ${ - plural ? 'are native dependencies' : 'is a native dependency' - } and should be installed inside of the "./release/app" folder. - First, uninstall the packages from "./package.json": -${chalk.whiteBright.bgGreen.bold('npm uninstall your-package')} - ${chalk.bold( - 'Then, instead of installing the package to the root "./package.json":' - )} -${chalk.whiteBright.bgRed.bold('npm install your-package')} - ${chalk.bold('Install the package to "./release/app/package.json"')} -${chalk.whiteBright.bgGreen.bold( - 'cd ./release/app && npm install your-package' -)} - Read more about native dependencies at: -${chalk.bold( - 'https://electron-react-boilerplate.js.org/docs/adding-dependencies/#module-structure' -)} - `); - process.exit(1); - } - } catch (e) { - console.log('Native dependencies could not be checked'); - } -} diff --git a/.erb/scripts/check-node-env.js b/.erb/scripts/check-node-env.js deleted file mode 100644 index 0e74b115..00000000 --- a/.erb/scripts/check-node-env.js +++ /dev/null @@ -1,16 +0,0 @@ -import chalk from 'chalk'; - -export default function checkNodeEnv(expectedEnv) { - if (!expectedEnv) { - throw new Error('"expectedEnv" not set'); - } - - if (process.env.NODE_ENV !== expectedEnv) { - console.log( - chalk.whiteBright.bgRed.bold( - `"process.env.NODE_ENV" must be "${expectedEnv}" to use this webpack config` - ) - ); - process.exit(2); - } -} diff --git a/.erb/scripts/check-port-in-use.js b/.erb/scripts/check-port-in-use.js deleted file mode 100644 index 9d74213d..00000000 --- a/.erb/scripts/check-port-in-use.js +++ /dev/null @@ -1,16 +0,0 @@ -import chalk from 'chalk'; -import detectPort from 'detect-port'; - -const port = process.env.PORT || '4343'; - -detectPort(port, (err, availablePort) => { - if (port !== String(availablePort)) { - throw new Error( - chalk.whiteBright.bgRed.bold( - `Port "${port}" on "localhost" is already in use. Please use another port. ex: PORT=4343 npm start` - ) - ); - } else { - process.exit(0); - } -}); diff --git a/.erb/scripts/clean.js b/.erb/scripts/clean.js deleted file mode 100644 index b03b0baf..00000000 --- a/.erb/scripts/clean.js +++ /dev/null @@ -1,17 +0,0 @@ -import rimraf from 'rimraf'; -import process from 'process'; -import webpackPaths from '../configs/webpack.paths'; - -const args = process.argv.slice(2); -const commandMap = { - dist: webpackPaths.distPath, - release: webpackPaths.releasePath, - dll: webpackPaths.dllPath, -}; - -args.forEach((x) => { - const pathToRemove = commandMap[x]; - if (pathToRemove !== undefined) { - rimraf.sync(pathToRemove); - } -}); diff --git a/.erb/scripts/delete-source-maps.js b/.erb/scripts/delete-source-maps.js deleted file mode 100644 index 21d6cb58..00000000 --- a/.erb/scripts/delete-source-maps.js +++ /dev/null @@ -1,9 +0,0 @@ -import path from 'path'; -import rimraf from 'rimraf'; -import webpackPaths from '../configs/webpack.paths'; - -export default function deleteSourceMaps() { - rimraf.sync(path.join(webpackPaths.distMainPath, '*.js.map')); - rimraf.sync(path.join(webpackPaths.distRemotePath, '*.js.map')); - rimraf.sync(path.join(webpackPaths.distRendererPath, '*.js.map')); -} diff --git a/.erb/scripts/electron-rebuild.js b/.erb/scripts/electron-rebuild.js deleted file mode 100644 index 0bea3279..00000000 --- a/.erb/scripts/electron-rebuild.js +++ /dev/null @@ -1,20 +0,0 @@ -import { execSync } from 'child_process'; -import fs from 'fs'; -import { dependencies } from '../../release/app/package.json'; -import webpackPaths from '../configs/webpack.paths'; - -if ( - Object.keys(dependencies || {}).length > 0 && - fs.existsSync(webpackPaths.appNodeModulesPath) -) { - const electronRebuildCmd = - '../../node_modules/.bin/electron-rebuild --force --types prod,dev,optional --module-dir .'; - const cmd = - process.platform === 'win32' - ? electronRebuildCmd.replace(/\//g, '\\') - : electronRebuildCmd; - execSync(cmd, { - cwd: webpackPaths.appPath, - stdio: 'inherit', - }); -} diff --git a/.erb/scripts/link-modules.ts b/.erb/scripts/link-modules.ts deleted file mode 100644 index 6cc31e66..00000000 --- a/.erb/scripts/link-modules.ts +++ /dev/null @@ -1,9 +0,0 @@ -import fs from 'fs'; -import webpackPaths from '../configs/webpack.paths'; - -const { srcNodeModulesPath } = webpackPaths; -const { appNodeModulesPath } = webpackPaths; - -if (!fs.existsSync(srcNodeModulesPath) && fs.existsSync(appNodeModulesPath)) { - fs.symlinkSync(appNodeModulesPath, srcNodeModulesPath, 'junction'); -} diff --git a/.erb/scripts/notarize.js b/.erb/scripts/notarize.js deleted file mode 100644 index 4fd3bb8f..00000000 --- a/.erb/scripts/notarize.js +++ /dev/null @@ -1,30 +0,0 @@ -const { notarize } = require('electron-notarize'); -const { build } = require('../../package.json'); - -exports.default = async function notarizeMacos(context) { - const { electronPlatformName, appOutDir } = context; - if (electronPlatformName !== 'darwin') { - return; - } - - if (process.env.CI !== 'true') { - console.warn('Skipping notarizing step. Packaging is not running in CI'); - return; - } - - if (!('APPLE_ID' in process.env && 'APPLE_ID_PASS' in process.env)) { - console.warn( - 'Skipping notarizing step. APPLE_ID and APPLE_ID_PASS env variables must be set' - ); - return; - } - - const appName = context.packager.appInfo.productFilename; - - await notarize({ - appBundleId: build.appId, - appPath: `${appOutDir}/${appName}.app`, - appleId: process.env.APPLE_ID, - appleIdPassword: process.env.APPLE_ID_PASS, - }); -}; diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 19391098..00000000 --- a/.eslintignore +++ /dev/null @@ -1,34 +0,0 @@ -# Logs -logs -*.log - -# Runtime data -pids -*.pid -*.seed - -# Coverage directory used by tools like istanbul -coverage -.eslintcache - -# Dependency directory -# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git -node_modules - -# OSX -.DS_Store - -src/i18n -release/app/dist -release/build -.erb/dll - -.idea -npm-debug.log.* -*.css.d.ts -*.sass.d.ts -*.scss.d.ts - -# eslint ignores hidden directories by default: -# https://github.com/eslint/eslint/issues/8429 -!.erb diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index ecc54801..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,97 +0,0 @@ -module.exports = { - extends: ['erb', 'plugin:typescript-sort-keys/recommended'], - ignorePatterns: ['.erb/*', 'server'], - parser: '@typescript-eslint/parser', - parserOptions: { - createDefaultProgram: true, - ecmaVersion: 12, - parser: '@typescript-eslint/parser', - project: './tsconfig.json', - sourceType: 'module', - tsconfigRootDir: './', - }, - plugins: ['@typescript-eslint', 'import', 'sort-keys-fix'], - rules: { - '@typescript-eslint/naming-convention': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-shadow': ['off'], - '@typescript-eslint/no-unused-vars': ['error'], - '@typescript-eslint/no-use-before-define': ['error'], - 'default-case': 'off', - 'import/extensions': 'off', - 'import/no-absolute-path': 'off', - // A temporary hack related to IDE not resolving correct package.json - 'import/no-extraneous-dependencies': 'off', - 'import/no-unresolved': 'error', - 'import/order': [ - 'error', - { - alphabetize: { - caseInsensitive: true, - order: 'asc', - }, - groups: ['builtin', 'external', 'internal', ['parent', 'sibling']], - 'newlines-between': 'never', - pathGroups: [ - { - group: 'external', - pattern: 'react', - position: 'before', - }, - ], - pathGroupsExcludedImportTypes: ['react'], - }, - ], - 'import/prefer-default-export': 'off', - 'jsx-a11y/click-events-have-key-events': 'off', - 'jsx-a11y/interactive-supports-focus': 'off', - 'jsx-a11y/media-has-caption': 'off', - 'no-await-in-loop': 'off', - 'no-console': 'off', - 'no-nested-ternary': 'off', - 'no-restricted-syntax': 'off', - 'no-shadow': 'off', - 'no-underscore-dangle': 'off', - 'no-unused-vars': 'off', - 'no-use-before-define': 'off', - 'prefer-destructuring': 'off', - 'react/function-component-definition': 'off', - 'react/jsx-filename-extension': [2, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }], - 'react/jsx-no-useless-fragment': 'off', - 'react/jsx-props-no-spreading': 'off', - 'react/jsx-sort-props': [ - 'error', - { - callbacksLast: true, - ignoreCase: false, - noSortAlphabetically: false, - reservedFirst: true, - shorthandFirst: true, - shorthandLast: false, - }, - ], - 'react/no-array-index-key': 'off', - 'react/react-in-jsx-scope': 'off', - 'react/require-default-props': 'off', - 'sort-keys-fix/sort-keys-fix': 'warn', - }, - settings: { - 'import/parsers': { - '@typescript-eslint/parser': ['.ts', '.tsx'], - }, - 'import/resolver': { - // See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below - node: { - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }, - typescript: { - alwaysTryTypes: true, - project: './tsconfig.json', - }, - webpack: { - config: require.resolve('./.erb/configs/webpack.config.eslint.ts'), - }, - }, - }, -}; diff --git a/.gitignore b/.gitignore index c19e33ce..75ef73cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,31 +1,6 @@ -# Logs -logs -*.log - -# Runtime data -pids -*.pid -*.seed - -# Coverage directory used by tools like istanbul -coverage -.eslintcache - -# Dependency directory -# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules - -# OSX +dist +out .DS_Store - -release/app/dist -release/build -.erb/dll - -.idea -npm-debug.log.* -*.css.d.ts -*.sass.d.ts -*.scss.d.ts - -.env* +.eslintcache +*.log* diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 36af2198..00000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx lint-staged diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..9c6b791d --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +out +dist +pnpm-lock.yaml +LICENSE.md +tsconfig.json +tsconfig.*.json diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index d0e0490c..00000000 --- a/.prettierrc +++ /dev/null @@ -1,22 +0,0 @@ -{ - "printWidth": 100, - "semi": true, - "singleQuote": true, - "tabWidth": 4, - "useTabs": false, - "overrides": [ - { - "files": ["**/*.css", "**/*.scss", "**/*.html"], - "options": { - "singleQuote": true - } - } - ], - "trailingComma": "all", - "bracketSpacing": true, - "arrowParens": "always", - "proseWrap": "never", - "htmlWhitespaceSensitivity": "strict", - "endOfLine": "lf", - "singleAttributePerLine": true -} diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 00000000..357f740e --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,12 @@ +singleQuote: true +semi: true +printWidth: 100 +tabWidth: 4 +trailingComma: all +useTabs: false +arrowParens: always +proseWrap: never +htmlWhitespaceSensitivity: strict +endOfLine: lf +singleAttributePerLine: true +bracketSpacing: true diff --git a/.vscode/extensions.json b/.vscode/extensions.json index c10cabc4..940260d8 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,10 +1,3 @@ { - "recommendations": [ - "dbaeumer.vscode-eslint", - "EditorConfig.EditorConfig", - "stylelint.vscode-stylelint", - "esbenp.prettier-vscode", - "clinyong.vscode-css-modules", - "Huuums.vscode-fast-folder-structure" - ] + "recommendations": ["dbaeumer.vscode-eslint"] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 9c06cf39..0b6b9a64 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,28 +1,39 @@ { - "version": "0.2.0", - "configurations": [ - { - "name": "Electron: Main", - "type": "node", - "request": "launch", - "protocol": "inspector", - "runtimeExecutable": "npm", - "runtimeArgs": ["run start:main --inspect=5858 --remote-debugging-port=9223"], - "preLaunchTask": "Start Webpack Dev" - }, - { - "name": "Electron: Renderer", - "type": "chrome", - "request": "attach", - "port": 9223, - "webRoot": "${workspaceFolder}", - "timeout": 15000 - } - ], - "compounds": [ - { - "name": "Electron: All", - "configurations": ["Electron: Main", "Electron: Renderer"] - } - ] + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Main Process", + "type": "node", + "request": "launch", + "cwd": "${workspaceRoot}", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite", + "windows": { + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd" + }, + "runtimeArgs": ["--sourcemap"], + "env": { + "REMOTE_DEBUGGING_PORT": "9222" + } + }, + { + "name": "Debug Renderer Process", + "port": 9222, + "request": "attach", + "type": "chrome", + "webRoot": "${workspaceFolder}/src/renderer", + "timeout": 60000, + "presentation": { + "hidden": true + } + } + ], + "compounds": [ + { + "name": "Debug All", + "configurations": ["Debug Main Process", "Debug Renderer Process"], + "presentation": { + "order": 1 + } + } + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 04145377..89839241 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,13 @@ { + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, "files.associations": { ".eslintrc": "jsonc", ".prettierrc": "jsonc", @@ -40,7 +49,6 @@ "typescript.preferences.importModuleSpecifier": "non-relative", "stylelint.validate": ["css", "scss", "typescript", "typescriptreact"], "typescript.updateImportsOnFileMove.enabled": "always", - "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": true, "folderTemplates.structures": [ diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index e0c639bd..00000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "label": "Start Webpack Dev", - "script": "start:renderer", - "options": { - "cwd": "${workspaceFolder}" - }, - "isBackground": true, - "problemMatcher": { - "owner": "custom", - "pattern": { - "regexp": "____________" - }, - "background": { - "activeOnStart": true, - "beginsPattern": "Compiling\\.\\.\\.$", - "endsPattern": "(Compiled successfully|Failed to compile)\\.$" - } - } - } - ] -} diff --git a/build/entitlements.mac.plist b/build/entitlements.mac.plist new file mode 100644 index 00000000..38c887b2 --- /dev/null +++ b/build/entitlements.mac.plist @@ -0,0 +1,12 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.allow-dyld-environment-variables + + + diff --git a/build/icon.icns b/build/icon.icns new file mode 100644 index 00000000..93da8771 Binary files /dev/null and b/build/icon.icns differ diff --git a/build/icon.ico b/build/icon.ico new file mode 100644 index 00000000..1e9d1e04 Binary files /dev/null and b/build/icon.ico differ diff --git a/build/icon.png b/build/icon.png new file mode 100644 index 00000000..f364f2c1 Binary files /dev/null and b/build/icon.png differ diff --git a/dev-app-update.yml b/dev-app-update.yml new file mode 100644 index 00000000..44ae7a59 --- /dev/null +++ b/dev-app-update.yml @@ -0,0 +1,3 @@ +provider: generic +url: https://example.com/auto-updates +updaterCacheDirName: feishin-updater diff --git a/electron-builder.yml b/electron-builder.yml new file mode 100644 index 00000000..97210c58 --- /dev/null +++ b/electron-builder.yml @@ -0,0 +1,43 @@ +appId: com.electron.app +productName: feishin +directories: + buildResources: build +files: + - '!**/.vscode/*' + - '!src/*' + - '!electron.vite.config.{js,ts,mjs,cjs}' + - '!{.eslintcache,eslint.config.mjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' + - '!{.env,.env.*,.npmrc,pnpm-lock.yaml}' + - '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}' +asarUnpack: + - resources/** +win: + executableName: feishin +nsis: + artifactName: ${name}-${version}-setup.${ext} + shortcutName: ${productName} + uninstallDisplayName: ${productName} + createDesktopShortcut: always +mac: + entitlementsInherit: build/entitlements.mac.plist + extendInfo: + - NSCameraUsageDescription: Application requests access to the device's camera. + - NSMicrophoneUsageDescription: Application requests access to the device's microphone. + - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. + - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. + notarize: false +dmg: + artifactName: ${name}-${version}.${ext} +linux: + target: + - AppImage + - snap + - deb + maintainer: electronjs.org + category: Utility +appImage: + artifactName: ${name}-${version}.${ext} +npmRebuild: false +publish: + provider: generic + url: https://example.com/auto-updates diff --git a/electron.vite.config.ts b/electron.vite.config.ts new file mode 100644 index 00000000..c338aacc --- /dev/null +++ b/electron.vite.config.ts @@ -0,0 +1,35 @@ +import react from '@vitejs/plugin-react'; +import { externalizeDepsPlugin, UserConfig } from 'electron-vite'; +import { resolve } from 'path'; + +const config: UserConfig = { + main: { + plugins: [externalizeDepsPlugin()], + }, + preload: { + plugins: [externalizeDepsPlugin()], + }, + renderer: { + css: { + modules: { + generateScopedName: '[name]__[local]__[hash:base64:5]', + localsConvention: 'camelCase', + }, + }, + plugins: [react()], + resolve: { + alias: { + '/@/i18n': resolve('src/i18n'), + '/@/main': resolve('src/main'), + '/@/renderer': resolve('src/renderer'), + '/@/renderer/api': resolve('src/renderer/api'), + '/@/renderer/components': resolve('src/renderer/components'), + '/@/renderer/features': resolve('src/renderer/features'), + '/@/renderer/hooks': resolve('src/renderer/hooks'), + '/@/shared': resolve('src/shared'), + }, + }, + }, +}; + +export default config; diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..b286f9b3 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,48 @@ +import eslintConfigPrettier from '@electron-toolkit/eslint-config-prettier'; +import tseslint from '@electron-toolkit/eslint-config-ts'; +import perfectionist from 'eslint-plugin-perfectionist'; +import eslintPluginReact from 'eslint-plugin-react'; +import eslintPluginReactHooks from 'eslint-plugin-react-hooks'; +import eslintPluginReactRefresh from 'eslint-plugin-react-refresh'; + +export default tseslint.config( + { ignores: ['**/node_modules', '**/dist', '**/out'] }, + tseslint.configs.recommended, + perfectionist.configs['recommended-natural'], + eslintPluginReact.configs.flat.recommended, + eslintPluginReact.configs.flat['jsx-runtime'], + { + settings: { + react: { + version: 'detect', + }, + }, + }, + { + files: ['**/*.{ts,tsx}'], + plugins: { + 'react-hooks': eslintPluginReactHooks, + 'react-refresh': eslintPluginReactRefresh, + }, + rules: { + ...eslintPluginReactHooks.configs.recommended.rules, + ...eslintPluginReactRefresh.configs.vite.rules, + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-unused-vars': 'warn', + curly: ['error', 'all'], + indent: [ + 'error', + 'tab', + { + offsetTernaryExpressions: true, + SwitchCase: 1, + }, + ], + 'no-unused-vars': 'off', + 'no-use-before-define': 'off', + quotes: ['error', 'single'], + semi: ['error', 'always'], + }, + }, + eslintConfigPrettier, +); diff --git a/ng.conf.template b/ng.conf.template deleted file mode 100644 index eb46ff72..00000000 --- a/ng.conf.template +++ /dev/null @@ -1,27 +0,0 @@ -server { - listen 9180; - sendfile on; - default_type application/octet-stream; - - gzip on; - gzip_http_version 1.1; - gzip_disable "MSIE [1-6]\."; - gzip_min_length 256; - gzip_vary on; - gzip_proxied expired no-cache no-store private auth; - gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; - gzip_comp_level 9; - - location ${PUBLIC_PATH} { - alias /usr/share/nginx/html/; - try_files $uri $uri/ /index.html =404; - } - - location ${PUBLIC_PATH}settings.js { - alias /etc/nginx/conf.d/settings.js; - } - - location ${PUBLIC_PATH}/settings.js { - alias /etc/nginx/conf.d/settings.js; - } -} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2f03474d..9bf65edf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,14 @@ "name": "feishin", "version": "0.13.0", "hasInstallScript": true, - "license": "GPL-3.0", "dependencies": { "@ag-grid-community/client-side-row-model": "^28.2.1", "@ag-grid-community/core": "^28.2.1", "@ag-grid-community/infinite-row-model": "^28.2.1", "@ag-grid-community/react": "^28.2.1", "@ag-grid-community/styles": "^28.2.1", + "@electron-toolkit/preload": "^3.0.1", + "@electron-toolkit/utils": "^4.0.0", "@emotion/react": "^11.10.4", "@mantine/core": "^6.0.17", "@mantine/dates": "^6.0.17", @@ -31,6 +32,7 @@ "audiomotion-analyzer": "^4.5.0", "auto-text-size": "^0.2.3", "axios": "^1.6.0", + "cheerio": "^1.0.0", "clsx": "^2.0.0", "cmdk": "^0.2.0", "dayjs": "^1.11.6", @@ -39,7 +41,7 @@ "electron-localshortcut": "^3.2.1", "electron-log": "^5.1.1", "electron-store": "^8.1.0", - "electron-updater": "^6.3.1", + "electron-updater": "^6.3.9", "fast-average-color": "^9.3.0", "format-duration": "^2.0.0", "framer-motion": "^11.0.0", @@ -52,11 +54,12 @@ "lodash": "^4.17.21", "md5": "^2.3.0", "memoize-one": "^6.0.0", + "mpris-service": "^2.1.2", "nanoid": "^3.3.3", "net": "^1.0.2", "node-mpv": "github:jeffvli/Node-MPV#32b4d64395289ad710c41d481d2707a7acfc228f", - "overlayscrollbars": "^2.2.1", - "overlayscrollbars-react": "^0.5.1", + "overlayscrollbars": "^2.11.1", + "overlayscrollbars-react": "^0.5.6", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", @@ -72,10 +75,14 @@ "semver": "^7.5.4", "styled-components": "^6.0.8", "swiper": "^9.3.1", + "ws": "^8.18.2", "zod": "^3.22.3", "zustand": "^4.3.9" }, "devDependencies": { + "@electron-toolkit/eslint-config-prettier": "^3.0.0", + "@electron-toolkit/eslint-config-ts": "^3.0.0", + "@electron-toolkit/tsconfig": "^1.0.1", "@electron/rebuild": "^3.6.0", "@pmmmwh/react-refresh-webpack-plugin": "0.5.5", "@stylelint/postcss-css-in-js": "^0.38.0", @@ -87,9 +94,9 @@ "@types/jest": "^27.4.1", "@types/lodash": "^4.14.188", "@types/md5": "^2.3.2", - "@types/node": "^17.0.23", - "@types/react": "^18.0.25", - "@types/react-dom": "^18.0.8", + "@types/node": "^22.14.1", + "@types/react": "^19.1.1", + "@types/react-dom": "^19.1.2", "@types/react-test-renderer": "^17.0.1", "@types/react-virtualized-auto-sizer": "^1.0.1", "@types/react-window": "^1.8.5", @@ -100,6 +107,7 @@ "@types/webpack-env": "^1.16.3", "@typescript-eslint/eslint-plugin": "^5.47.0", "@typescript-eslint/parser": "^5.47.0", + "@vitejs/plugin-react": "^4.3.4", "browserslist-config-erb": "^0.0.3", "chalk": "^4.1.2", "concurrently": "^7.1.0", @@ -108,12 +116,13 @@ "css-loader": "^6.7.1", "css-minimizer-webpack-plugin": "^3.4.1", "detect-port": "^1.3.0", - "electron": "^36.1.0", - "electron-builder": "^24.13.3", + "electron": "^35.1.5", + "electron-builder": "^25.1.8", "electron-devtools-installer": "^3.2.0", "electron-notarize": "^1.2.1", + "electron-vite": "^3.1.0", "electronmon": "^2.0.2", - "eslint": "^8.30.0", + "eslint": "^9.24.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-erb": "^4.0.3", "eslint-import-resolver-typescript": "^2.7.1", @@ -122,9 +131,12 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-jest": "^26.1.3", "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-perfectionist": "^4.13.0", + "eslint-plugin-prettier": "^5.4.0", "eslint-plugin-promise": "^6.0.0", - "eslint-plugin-react": "^7.29.4", - "eslint-plugin-react-hooks": "^4.4.0", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.19", "eslint-plugin-sort-keys-fix": "^1.1.2", "eslint-plugin-typescript-sort-keys": "^2.1.0", "file-loader": "^6.2.0", @@ -138,12 +150,15 @@ "postcss-scss": "^4.0.4", "postcss-styled-syntax": "^0.5.0", "postcss-syntax": "^0.36.2", - "prettier": "^3.3.3", + "prettier": "^3.5.3", + "react": "^19.1.0", + "react-dom": "^19.1.0", "react-refresh": "^0.12.0", "react-refresh-typescript": "^2.0.4", "react-test-renderer": "^18.0.0", "rimraf": "^3.0.2", "sass": "^1.49.11", + "sass-embedded": "^1.89.0", "sass-loader": "^12.6.0", "style-loader": "^3.3.1", "stylelint": "^15.10.3", @@ -158,9 +173,10 @@ "ts-node": "^10.9.2", "tsconfig-paths-webpack-plugin": "^4.0.0", "tsx": "^4.16.2", - "typescript": "^5.2.2", + "typescript": "^5.8.3", "typescript-plugin-styled-components": "^3.0.0", "url-loader": "^4.1.1", + "vite": "^6.2.6", "webpack": "^5.94.0", "webpack-bundle-analyzer": "^4.5.0", "webpack-cli": "^4.9.2", @@ -234,23 +250,23 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", + "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", "dev": true, "license": "MIT", "engines": { @@ -258,22 +274,22 @@ } }, "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", + "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helpers": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -306,13 +322,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", + "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", + "@babel/parser": "^7.27.1", + "@babel/types": "^7.27.1", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -322,14 +338,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -349,28 +365,28 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", + "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -380,9 +396,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, "license": "MIT", "engines": { @@ -390,27 +406,27 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", "engines": { @@ -418,26 +434,26 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", + "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", + "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.0" + "@babel/types": "^7.27.1" }, "bin": { "parser": "bin/babel-parser.js" @@ -502,13 +518,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -654,13 +670,61 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -670,42 +734,39 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", + "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", + "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -713,14 +774,23 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", + "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -733,6 +803,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@bufbuild/protobuf": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.4.0.tgz", + "integrity": "sha512-RN9M76x7N11QRihKovEglEjjVCQEA9PRBVnDgk9xw8JHLrcUrp4FpAVSPSH91cNbcTft3u2vpLN4GMbiKY9PJw==", + "dev": true, + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -878,9 +955,9 @@ } }, "node_modules/@discordjs/rest": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.4.3.tgz", - "integrity": "sha512-+SO4RKvWsM+y8uFHgYQrcTl/3+cY02uQOH7/7bKbVZsTfrfpoE62o5p+mmV+s7FVhTX82/kQUGGbu4YlV60RtA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.5.0.tgz", + "integrity": "sha512-PWhchxTzpn9EV3vvPRpwS0EE2rNYB9pvzDU/eLLW3mByJl0ZHZjHI2/wA8EbH2gRMQV7nu+0FoDF84oiPl8VAQ==", "license": "Apache-2.0", "dependencies": { "@discordjs/collection": "^2.1.1", @@ -888,7 +965,7 @@ "@sapphire/async-queue": "^1.5.3", "@sapphire/snowflake": "^3.5.3", "@vladfrangu/async_event_emitter": "^2.4.6", - "discord-api-types": "^0.37.119", + "discord-api-types": "^0.38.1", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.1" @@ -900,6 +977,15 @@ "url": "https://github.com/discordjs/discord.js?sponsor" } }, + "node_modules/@discordjs/rest/node_modules/discord-api-types": { + "version": "0.38.8", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.38.8.tgz", + "integrity": "sha512-xuRXPD44FcbKHrQK15FS1HFlMRNJtsaZou/SVws18vQ7zHqmlxyDktMkZpyvD6gE2ctGOVYC/jUyoMMAyBWfcw==", + "license": "MIT", + "workspaces": [ + "scripts/actions/documentation" + ] + }, "node_modules/@discordjs/util": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.1.tgz", @@ -922,6 +1008,70 @@ "node": ">=10.0.0" } }, + "node_modules/@electron-toolkit/eslint-config-prettier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@electron-toolkit/eslint-config-prettier/-/eslint-config-prettier-3.0.0.tgz", + "integrity": "sha512-YapmIOVkbYdHLuTa+ad1SAVtcqYL9A/SJsc7cxQokmhcwAwonGevNom37jBf9slXegcZ/Slh01I/JARG1yhNFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-prettier": "^5.2.3" + }, + "peerDependencies": { + "eslint": ">= 9.0.0", + "prettier": ">= 3.0.0" + } + }, + "node_modules/@electron-toolkit/eslint-config-ts": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@electron-toolkit/eslint-config-ts/-/eslint-config-ts-3.1.0.tgz", + "integrity": "sha512-MowZQKd3yxXSDLack5QvjQwYHhpOJFoWBGBwJ/k+DCd7NUSendplECbQGFp86tPQYPUrPBPceR/hdsSAnaY5ZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/js": "^9.24.0", + "globals": "^16.0.0", + "typescript-eslint": "^8.29.1" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@electron-toolkit/preload": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@electron-toolkit/preload/-/preload-3.0.2.tgz", + "integrity": "sha512-TWWPToXd8qPRfSXwzf5KVhpXMfONaUuRAZJHsKthKgZR/+LqX1dZVSSClQ8OTAEduvLGdecljCsoT2jSshfoUg==", + "license": "MIT", + "peerDependencies": { + "electron": ">=13.0.0" + } + }, + "node_modules/@electron-toolkit/tsconfig": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@electron-toolkit/tsconfig/-/tsconfig-1.0.1.tgz", + "integrity": "sha512-M0Mol3odspvtCuheyujLNAW7bXq7KFNYVMRtpjFa4ZfES4MuklXBC7Nli/omvc+PRKlrklgAGx3l4VakjNo8jg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/node": "*" + } + }, + "node_modules/@electron-toolkit/utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@electron-toolkit/utils/-/utils-4.0.0.tgz", + "integrity": "sha512-qXSntwEzluSzKl4z5yFNBknmPGjPa3zFhE4mp9+h0cgokY5ornAeP+CJQDBhKsL1S58aOQfcwkD3NwLZCl+64g==", + "license": "MIT", + "peerDependencies": { + "electron": ">=13.0.0" + } + }, "node_modules/@electron/asar": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", @@ -1056,7 +1206,7 @@ "node_modules/@electron/node-gyp": { "version": "10.2.0-electron.1", "resolved": "git+ssh://git@github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", - "integrity": "sha512-CrYo6TntjpoMO1SHjl5Pa/JoUsECNqNdB7Kx49WLQpWzPw53eEITJ2Hs9fh/ryUYDn4pxZz11StaBYBrLFJdqg==", + "integrity": "sha512-4MSBTT8y07YUDqf69/vSh80Hh791epYqGtWHO3zSKhYFwQg+gx9wi1PqbqP6YqC4WMsNxZ5l9oDmnWdK5pfCKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1079,9 +1229,9 @@ } }, "node_modules/@electron/notarize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", - "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", + "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==", "dev": true, "license": "MIT", "dependencies": { @@ -1110,9 +1260,9 @@ } }, "node_modules/@electron/osx-sign": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", - "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz", + "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -1174,85 +1324,53 @@ } }, "node_modules/@electron/universal": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", - "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", + "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", "dev": true, "license": "MIT", "dependencies": { - "@electron/asar": "^3.2.1", - "@malept/cross-spawn-promise": "^1.1.0", + "@electron/asar": "^3.2.7", + "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", - "dir-compare": "^3.0.0", - "fs-extra": "^9.0.1", - "minimatch": "^3.0.4", - "plist": "^3.0.4" + "dir-compare": "^4.2.0", + "fs-extra": "^11.1.1", + "minimatch": "^9.0.3", + "plist": "^3.1.0" }, "engines": { - "node": ">=8.6" - } - }, - "node_modules/@electron/universal/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@electron/universal/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": ">=16.4" } }, "node_modules/@electron/universal/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "dev": true, "license": "MIT", "dependencies": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=14.14" } }, "node_modules/@electron/universal/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@emotion/babel-plugin": { @@ -1385,9 +1503,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", - "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", "cpu": [ "ppc64" ], @@ -1402,9 +1520,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", - "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", "cpu": [ "arm" ], @@ -1419,9 +1537,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", - "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", "cpu": [ "arm64" ], @@ -1436,9 +1554,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", - "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", "cpu": [ "x64" ], @@ -1453,9 +1571,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", - "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", "cpu": [ "arm64" ], @@ -1470,9 +1588,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", - "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", "cpu": [ "x64" ], @@ -1487,9 +1605,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", - "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", "cpu": [ "arm64" ], @@ -1504,9 +1622,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", - "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", "cpu": [ "x64" ], @@ -1521,9 +1639,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", - "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", "cpu": [ "arm" ], @@ -1538,9 +1656,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", - "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", "cpu": [ "arm64" ], @@ -1555,9 +1673,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", - "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", "cpu": [ "ia32" ], @@ -1572,9 +1690,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", - "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", "cpu": [ "loong64" ], @@ -1589,9 +1707,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", - "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", "cpu": [ "mips64el" ], @@ -1606,9 +1724,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", - "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", "cpu": [ "ppc64" ], @@ -1623,9 +1741,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", - "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", "cpu": [ "riscv64" ], @@ -1640,9 +1758,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", - "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", "cpu": [ "s390x" ], @@ -1657,9 +1775,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", - "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", "cpu": [ "x64" ], @@ -1674,9 +1792,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", - "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", "cpu": [ "arm64" ], @@ -1691,9 +1809,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", - "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", "cpu": [ "x64" ], @@ -1708,9 +1826,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", - "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", "cpu": [ "arm64" ], @@ -1725,9 +1843,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", - "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", "cpu": [ "x64" ], @@ -1742,9 +1860,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", - "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", "cpu": [ "x64" ], @@ -1759,9 +1877,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", - "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", "cpu": [ "arm64" ], @@ -1776,9 +1894,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", - "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", "cpu": [ "ia32" ], @@ -1793,9 +1911,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", - "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", "cpu": [ "x64" ], @@ -1810,9 +1928,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", - "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, "license": "MIT", "dependencies": { @@ -1838,17 +1956,79 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", + "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -1856,7 +2036,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1874,16 +2054,13 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1902,45 +2079,59 @@ "node": "*" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "version": "9.27.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", + "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==", "dev": true, "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", + "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.14.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@floating-ui/core": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", - "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz", + "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==", "license": "MIT", "dependencies": { "@floating-ui/utils": "^0.2.9" } }, "node_modules/@floating-ui/dom": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", - "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.0.tgz", + "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==", "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.6.0", + "@floating-ui/core": "^1.7.0", "@floating-ui/utils": "^0.2.9" } }, @@ -1998,44 +2189,42 @@ "node": ">=10.13.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "Apache-2.0", "engines": { - "node": "*" + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/module-importer": { @@ -2052,18 +2241,25 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, "license": "ISC", "dependencies": { "string-width": "^5.1.2", @@ -2081,6 +2277,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -2093,6 +2290,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -2105,6 +2303,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", @@ -2122,6 +2321,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -2137,6 +2337,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", @@ -2893,6 +3094,15 @@ "node": ">= 8" } }, + "node_modules/@nornagon/put": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@nornagon/put/-/put-0.0.8.tgz", + "integrity": "sha512-ugvXJjwF5ldtUpa7D95kruNJ41yFQDEKyF5CW4TgKJnh+W/zmlBzXXeKTyqIgwMFrkePN2JqOBqcF0M0oOunow==", + "license": "MIT/X11", + "engines": { + "node": ">=0.3.0" + } + }, "node_modules/@npmcli/fs": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", @@ -3756,6 +3966,286 @@ "node": ">=14.0.0" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.0.tgz", + "integrity": "sha512-KxN+zCjOYHGwCl4UCtSfZ6jrq/qi88JDUtiEFk8LELEHq2Egfc/FgW+jItZiOLRuQfb/3xJSgFuNPC9jzggX+A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.0.tgz", + "integrity": "sha512-yDvqx3lWlcugozax3DItKJI5j05B0d4Kvnjx+5mwiUpWramVvmAByYigMplaoAQ3pvdprGCTCE03eduqE/8mPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.0.tgz", + "integrity": "sha512-2KOU574vD3gzcPSjxO0eyR5iWlnxxtmW1F5CkNOHmMlueKNCQkxR6+ekgWyVnz6zaZihpUNkGxjsYrkTJKhkaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.0.tgz", + "integrity": "sha512-gE5ACNSxHcEZyP2BA9TuTakfZvULEW4YAOtxl/A/YDbIir/wPKukde0BNPlnBiP88ecaN4BJI2TtAd+HKuZPQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.0.tgz", + "integrity": "sha512-GSxU6r5HnWij7FoSo7cZg3l5GPg4HFLkzsFFh0N/b16q5buW1NAWuCJ+HMtIdUEi6XF0qH+hN0TEd78laRp7Dg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.0.tgz", + "integrity": "sha512-KGiGKGDg8qLRyOWmk6IeiHJzsN/OYxO6nSbT0Vj4MwjS2XQy/5emsmtoqLAabqrohbgLWJ5GV3s/ljdrIr8Qjg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.0.tgz", + "integrity": "sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.0.tgz", + "integrity": "sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.0.tgz", + "integrity": "sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.0.tgz", + "integrity": "sha512-l+QK99je2zUKGd31Gh+45c4pGDAqZSuWQiuRFCdHYC2CSiO47qUWsCcenrI6p22hvHZrDje9QjwSMAFL3iwXwQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.0.tgz", + "integrity": "sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.0.tgz", + "integrity": "sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.0.tgz", + "integrity": "sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.0.tgz", + "integrity": "sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.0.tgz", + "integrity": "sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.0.tgz", + "integrity": "sha512-XMLeKjyH8NsEDCRptf6LO8lJk23o9wvB+dJwcXMaH6ZQbbkHu2dbGIUindbMtRN6ux1xKi16iXWu6q9mu7gDhQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.0.tgz", + "integrity": "sha512-m/P7LycHZTvSQeXhFmgmdqEiTqSV80zn6xHaQ1JSqwCtD1YGtwEK515Qmy9DcB2HK4dOUVypQxvhVSy06cJPEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.0.tgz", + "integrity": "sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.0.tgz", + "integrity": "sha512-tmazCrAsKzdkXssEc65zIE1oC6xPHwfy9d5Ta25SRCDOZS+I6RypVVShWALNuU9bxIfGA0aqrmzlzoM5wO5SPQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.0.tgz", + "integrity": "sha512-h1J+Yzjo/X+0EAvR2kIXJDuTuyT7drc+t2ALY0nIcGPbTatNOf0VWdhEA2Z4AAjv6X1NJV7SYo5oCTYRJhSlVA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -4038,6 +4528,39 @@ "deep-equal": "^2.0.5" } }, + "node_modules/@testing-library/dom/node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/@testing-library/jest-dom": { "version": "5.17.0", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", @@ -4094,14 +4617,24 @@ "react-dom": "^18.0.0" } }, + "node_modules/@testing-library/react/node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 10" + "node": ">= 6" } }, "node_modules/@trysound/sax": { @@ -4327,9 +4860,9 @@ "license": "MIT" }, "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "version": "4.17.22", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.22.tgz", + "integrity": "sha512-eZUmSnhRX9YRSkplpz0N+k6NljUUn5l3EWZIKZvYzhvMphEuNiyyy1viH/ejgt66JWgALwC/gtSUAeQKtSwW/w==", "dev": true, "license": "MIT", "dependencies": { @@ -4532,11 +5065,14 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "version": "22.15.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz", + "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } }, "node_modules/@types/node-forge": { "version": "1.3.11", @@ -4588,9 +5124,9 @@ "license": "MIT" }, "node_modules/@types/qs": { - "version": "6.9.18", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", - "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", "dev": true, "license": "MIT" }, @@ -4602,24 +5138,23 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.20", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz", - "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==", + "version": "19.1.4", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.4.tgz", + "integrity": "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==", "dev": true, "license": "MIT", "dependencies": { - "@types/prop-types": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.3.6", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.6.tgz", - "integrity": "sha512-nf22//wEbKXusP6E9pfOCDwFdHAX4u172eaJI4YkDRQEZiorm6KfYnSC2SWLDMVWUOWPERmJnN0ujeAfTBLvrw==", + "version": "19.1.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.5.tgz", + "integrity": "sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==", "dev": true, "license": "MIT", "peerDependencies": { - "@types/react": "^18.0.0" + "@types/react": "^19.0.0" } }, "node_modules/@types/react-test-renderer": { @@ -5090,12 +5625,35 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "node_modules/@vitejs/plugin-react": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz", + "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "@babel/core": "^7.26.10", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/@vitejs/plugin-react/node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/@vladfrangu/async_event_emitter": { "version": "2.4.6", @@ -5368,6 +5926,25 @@ "dev": true, "license": "ISC" }, + "node_modules/abstract-socket": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/abstract-socket/-/abstract-socket-2.1.1.tgz", + "integrity": "sha512-YZJizsvS1aBua5Gd01woe4zuyYBGgSMeqDOB6/ChwdTI904KP6QGtJswXl4hcqWxbz86hQBe++HWV0hF1aGUtA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "dependencies": { + "bindings": "^1.2.1", + "nan": "^2.12.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -5460,16 +6037,13 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "4" - }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/agentkeepalive": { @@ -5611,6 +6185,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5620,6 +6195,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -5646,42 +6222,47 @@ } }, "node_modules/app-builder-bin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", - "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "version": "5.0.0-alpha.10", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.10.tgz", + "integrity": "sha512-Ev4jj3D7Bo+O0GPD2NMvJl+PGiBAfS7pUGawntBNpCbxtpncfUixqFj9z9Jme7V7s3LBGqsWZZP54fxBX3JKJw==", "dev": true, "license": "MIT" }, "node_modules/app-builder-lib": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", - "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", + "version": "25.1.8", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-25.1.8.tgz", + "integrity": "sha512-pCqe7dfsQFBABC1jeKZXQWhGcCPF3rPCXDdfqVKjIeWBcXzyC1iOWZdfFhGl+S9MyE/k//DFmC6FzuGAUudNDg==", "dev": true, "license": "MIT", "dependencies": { "@develar/schema-utils": "~2.6.5", - "@electron/notarize": "2.2.1", - "@electron/osx-sign": "1.0.5", - "@electron/universal": "1.5.1", + "@electron/notarize": "2.5.0", + "@electron/osx-sign": "1.3.1", + "@electron/rebuild": "3.6.1", + "@electron/universal": "2.0.1", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "builder-util": "25.1.7", + "builder-util-runtime": "9.2.10", "chromium-pickle-js": "^0.2.0", + "config-file-ts": "0.2.8-rc1", "debug": "^4.3.4", + "dotenv": "^16.4.5", + "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", - "electron-publish": "24.13.1", + "electron-publish": "25.1.7", "form-data": "^4.0.0", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", "is-ci": "^3.0.0", "isbinaryfile": "^5.0.0", "js-yaml": "^4.1.0", + "json5": "^2.2.3", "lazy-val": "^1.0.5", - "minimatch": "^5.1.1", - "read-config-file": "6.3.2", + "minimatch": "^10.0.0", + "resedit": "^1.7.0", "sanitize-filename": "^1.6.3", "semver": "^7.3.8", "tar": "^6.1.12", @@ -5691,8 +6272,59 @@ "node": ">=14.0.0" }, "peerDependencies": { - "dmg-builder": "24.13.3", - "electron-builder-squirrel-windows": "24.13.3" + "dmg-builder": "25.1.8", + "electron-builder-squirrel-windows": "25.1.8" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/rebuild": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.6.1.tgz", + "integrity": "sha512-f6596ZHpEq/YskUd8emYvOUne89ij8mQgjYFA5ru25QwbrRO+t1SImofdDv7kKOuWCmVOuU5tvfkbgGxIl3E/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@malept/cross-spawn-promise": "^2.0.0", + "chalk": "^4.0.0", + "debug": "^4.1.1", + "detect-libc": "^2.0.1", + "fs-extra": "^10.0.0", + "got": "^11.7.0", + "node-abi": "^3.45.0", + "node-api-version": "^0.2.0", + "node-gyp": "^9.0.0", + "ora": "^5.1.0", + "read-binary-file-arch": "^1.0.6", + "semver": "^7.3.5", + "tar": "^6.0.5", + "yargs": "^17.0.1" + }, + "bin": { + "electron-rebuild": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/arg": { @@ -5709,11 +6341,12 @@ "license": "Python-2.0" }, "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.5.tgz", + "integrity": "sha512-N+u63/2br5AG+OSrk0rIgFOYPSEYlkD7Yk5fq3LDole6QDIAbAFpbchE5fhBiUdRV2Fa8pWAaXvy+VK/maBeTA==", "license": "MIT", "dependencies": { + "caniuse-lite": "^1.0.30001718", "tslib": "^2.0.0" }, "engines": { @@ -6197,6 +6830,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, "license": "MIT" }, "node_modules/bare-events": { @@ -6258,6 +6892,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -6357,7 +7001,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, "license": "ISC" }, "node_modules/boolean": { @@ -6373,6 +7016,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -6485,9 +7129,9 @@ "license": "BSD-2-Clause" }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", + "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", "dev": true, "funding": [ { @@ -6505,10 +7149,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -6575,6 +7219,13 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-builder": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", + "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", + "dev": true, + "license": "MIT/X11" + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -6585,44 +7236,30 @@ "node": "*" } }, - "node_modules/buffer-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", - "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, "license": "MIT" }, "node_modules/builder-util": { - "version": "24.13.1", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", - "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", + "version": "25.1.7", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-25.1.7.tgz", + "integrity": "sha512-7jPjzBwEGRbwNcep0gGNpLXG9P94VA3CPAZQCzxkFXiV2GMQKlziMbY//rXPI7WKfhsvGgFXjTcXdBEwgXw9ww==", "dev": true, "license": "MIT", "dependencies": { "@types/debug": "^4.1.6", "7zip-bin": "~5.2.0", - "app-builder-bin": "4.0.0", + "app-builder-bin": "5.0.0-alpha.10", "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.2.4", + "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", "cross-spawn": "^7.0.3", "debug": "^4.3.4", "fs-extra": "^10.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", "is-ci": "^3.0.0", "js-yaml": "^4.1.0", "source-map-support": "^0.5.19", @@ -6631,9 +7268,9 @@ } }, "node_modules/builder-util-runtime": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", - "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", + "version": "9.2.10", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.10.tgz", + "integrity": "sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw==", "dev": true, "license": "MIT", "dependencies": { @@ -6654,6 +7291,16 @@ "node": ">= 0.8" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cacache": { "version": "16.1.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", @@ -6727,7 +7374,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.0", @@ -6759,7 +7405,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -6870,10 +7515,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001715", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz", - "integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==", - "dev": true, + "version": "1.0.30001718", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", + "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", "funding": [ { "type": "opencollective", @@ -6930,7 +7574,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", - "dev": true, "license": "MIT", "dependencies": { "cheerio-select": "^2.1.0", @@ -6956,7 +7599,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", @@ -7229,6 +7871,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -7241,8 +7884,19 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, "license": "MIT" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -7257,6 +7911,13 @@ "dev": true, "license": "MIT" }, + "node_modules/colorjs.io": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz", + "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", + "dev": true, + "license": "MIT" + }, "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -7453,14 +8114,14 @@ "license": "MIT" }, "node_modules/config-file-ts": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", - "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "version": "0.2.8-rc1", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz", + "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==", "dev": true, "license": "MIT", "dependencies": { - "glob": "^10.3.10", - "typescript": "^5.3.3" + "glob": "^10.3.12", + "typescript": "^5.4.3" } }, "node_modules/config-file-ts/node_modules/glob": { @@ -7527,6 +8188,13 @@ "node": ">=0.8" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true, + "license": "ISC" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -7589,9 +8257,9 @@ } }, "node_modules/core-js": { - "version": "3.41.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.41.0.tgz", - "integrity": "sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==", + "version": "3.42.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.42.0.tgz", + "integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7601,9 +8269,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.41.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.41.0.tgz", - "integrity": "sha512-71Gzp96T9YPk63aUvE5Q5qP+DryB4ZloUZPSOebGM88VNw8VNfvdA7z6kGA8iGOTEzAomsRidp4jXSmUIJsL+Q==", + "version": "3.42.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.42.0.tgz", + "integrity": "sha512-007bM04u91fF4kMgwom2I5cQxAFIy8jVulgr9eozILl/SZE53QOqnW/+vviC+wQWLv+AunBG+8Q0TLoeSsSxRQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7676,6 +8344,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -7873,7 +8542,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", @@ -7915,7 +8583,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">= 6" @@ -8206,6 +8873,24 @@ "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", "license": "MIT" }, + "node_modules/dbus-next": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/dbus-next/-/dbus-next-0.9.2.tgz", + "integrity": "sha512-tzQq/+wrTZ2yU+U5PoeXc97KABhX2v55C/T0finH3tSKYuI8H/SqppIFymBBrUHcK13LvEGY3vdj3ikPPenL5g==", + "license": "MIT", + "dependencies": { + "@nornagon/put": "0.0.8", + "event-stream": "3.3.4", + "hexy": "^0.2.10", + "jsbi": "^2.0.5", + "long": "^4.0.0", + "safe-buffer": "^5.1.1", + "xml2js": "^0.4.17" + }, + "optionalDependencies": { + "abstract-socket": "^2.0.0" + } + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -8229,9 +8914,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -8339,30 +9024,17 @@ "license": "MIT" }, "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "dev": true, + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", "object-is": "^1.1.5", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" + "regexp.prototype.flags": "^1.5.1" }, "engines": { "node": ">= 0.4" @@ -8437,7 +9109,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -8465,7 +9136,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", @@ -8488,6 +9158,13 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -8581,14 +9258,14 @@ } }, "node_modules/dir-compare": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", - "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", + "integrity": "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==", "dev": true, "license": "MIT", "dependencies": { - "buffer-equal": "^1.0.0", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5", + "p-limit": "^3.1.0 " } }, "node_modules/dir-compare/node_modules/brace-expansion": { @@ -8635,15 +9312,15 @@ "license": "MIT" }, "node_modules/dmg-builder": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", - "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", + "version": "25.1.8", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-25.1.8.tgz", + "integrity": "sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ==", "dev": true, "license": "MIT", "dependencies": { - "app-builder-lib": "24.13.3", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "app-builder-lib": "25.1.8", + "builder-util": "25.1.7", + "builder-util-runtime": "9.2.10", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" @@ -8693,16 +9370,16 @@ } }, "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, "node_modules/dom-accessibility-api": { @@ -8736,7 +9413,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", @@ -8747,21 +9423,10 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, "funding": [ { "type": "github", @@ -8798,7 +9463,6 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.3.0" @@ -8823,7 +9487,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", @@ -8861,21 +9524,33 @@ } }, "node_modules/dotenv": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", - "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", "dev": true, - "license": "BSD-2-Clause" + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } }, "node_modules/dunder-proto": { "version": "1.0.1", @@ -8895,13 +9570,13 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true, "license": "MIT" }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, "license": "MIT" }, "node_modules/ee-first": { @@ -8928,9 +9603,9 @@ } }, "node_modules/electron": { - "version": "36.1.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-36.1.0.tgz", - "integrity": "sha512-gnp3BnbKdGsVc7cm1qlEaZc8pJsR08mIs8H/yTo8gHEtFkGGJbDTVZOYNAfbQlL0aXh+ozv+CnyiNeDNkT1Upg==", + "version": "35.4.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-35.4.0.tgz", + "integrity": "sha512-VIPSNcUnic00aaE83w6BW4Dj1kE8A5DU0nVbvwqotN3+gseGunbP4WyHp/kfKXVKQj1S3No3HnYxU5LJmYbAtw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -8947,21 +9622,20 @@ } }, "node_modules/electron-builder": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", - "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", + "version": "25.1.8", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-25.1.8.tgz", + "integrity": "sha512-poRgAtUHHOnlzZnc9PK4nzG53xh74wj2Jy7jkTrqZ0MWPoHGh1M2+C//hGeYdA+4K8w4yiVCNYoLXF7ySj2Wig==", "dev": true, "license": "MIT", "dependencies": { - "app-builder-lib": "24.13.3", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "app-builder-lib": "25.1.8", + "builder-util": "25.1.7", + "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", - "dmg-builder": "24.13.3", + "dmg-builder": "25.1.8", "fs-extra": "^10.1.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", - "read-config-file": "6.3.2", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" }, @@ -9024,9 +9698,9 @@ } }, "node_modules/electron-log": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-5.3.4.tgz", - "integrity": "sha512-QLj0EbsA5R5Yy4vjGlLe7m8hPNZ/Enp7c7a2WH7RUPr0hIOp0vDaC+6bJM0th6+uZKiZGGH5a2aKzvYp3eYwDQ==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-5.4.0.tgz", + "integrity": "sha512-AXI5OVppskrWxEAmCxuv8ovX+s2Br39CpCAgkGMNHQtjYT3IiVbSQTncEjFVGPgoH35ZygRm/mvUMBDWwhRxgg==", "license": "MIT", "engines": { "node": ">= 14" @@ -9064,15 +9738,15 @@ } }, "node_modules/electron-publish": { - "version": "24.13.1", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", - "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", + "version": "25.1.7", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-25.1.7.tgz", + "integrity": "sha512-+jbTkR9m39eDBMP4gfbqglDd6UvBC7RLh5Y0MhFSsc6UkGHj9Vj9TWobxevHYMMqmoujL11ZLjfPpMX+Pt6YEg==", "dev": true, "license": "MIT", "dependencies": { "@types/fs-extra": "^9.0.11", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "builder-util": "25.1.7", + "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", @@ -9093,9 +9767,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.142", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.142.tgz", - "integrity": "sha512-Ah2HgkTu/9RhTDNThBtzu2Wirdy4DC9b0sMT1pUhbkZQ5U/iwmE+PHZX1MpjD5IkJCc2wSghgGG/B04szAx07w==", + "version": "1.5.155", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz", + "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==", "dev": true, "license": "ISC" }, @@ -9128,14 +9802,34 @@ "node": ">=12.0.0" } }, - "node_modules/electron/node_modules/@types/node": { - "version": "22.15.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.12.tgz", - "integrity": "sha512-K0fpC/ZVeb8G9rm7bH7vI0KAec4XHEhBam616nVJCV51bKzJ6oA3luG4WdKoaztxe70QaNjS/xBmcDLmr4PiGw==", + "node_modules/electron-vite": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/electron-vite/-/electron-vite-3.1.0.tgz", + "integrity": "sha512-M7aAzaRvSl5VO+6KN4neJCYLHLpF/iWo5ztchI/+wMxIieDZQqpbCYfaEHHHPH6eupEzfvZdLYdPdmvGqoVe0Q==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "@babel/core": "^7.26.10", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "cac": "^6.7.14", + "esbuild": "^0.25.1", + "magic-string": "^0.30.17", + "picocolors": "^1.1.1" + }, + "bin": { + "electron-vite": "bin/electron-vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@swc/core": "^1.0.0", + "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + } } }, "node_modules/electronmon": { @@ -9188,6 +9882,7 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, "license": "MIT" }, "node_modules/emojis-list": { @@ -9225,7 +9920,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==", - "dev": true, "license": "MIT", "dependencies": { "iconv-lite": "^0.6.3", @@ -9276,6 +9970,18 @@ "dev": true, "license": "ISC" }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -9538,9 +10244,9 @@ "optional": true }, "node_modules/esbuild": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", - "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -9551,31 +10257,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.3", - "@esbuild/android-arm": "0.25.3", - "@esbuild/android-arm64": "0.25.3", - "@esbuild/android-x64": "0.25.3", - "@esbuild/darwin-arm64": "0.25.3", - "@esbuild/darwin-x64": "0.25.3", - "@esbuild/freebsd-arm64": "0.25.3", - "@esbuild/freebsd-x64": "0.25.3", - "@esbuild/linux-arm": "0.25.3", - "@esbuild/linux-arm64": "0.25.3", - "@esbuild/linux-ia32": "0.25.3", - "@esbuild/linux-loong64": "0.25.3", - "@esbuild/linux-mips64el": "0.25.3", - "@esbuild/linux-ppc64": "0.25.3", - "@esbuild/linux-riscv64": "0.25.3", - "@esbuild/linux-s390x": "0.25.3", - "@esbuild/linux-x64": "0.25.3", - "@esbuild/netbsd-arm64": "0.25.3", - "@esbuild/netbsd-x64": "0.25.3", - "@esbuild/openbsd-arm64": "0.25.3", - "@esbuild/openbsd-x64": "0.25.3", - "@esbuild/sunos-x64": "0.25.3", - "@esbuild/win32-arm64": "0.25.3", - "@esbuild/win32-ia32": "0.25.3", - "@esbuild/win32-x64": "0.25.3" + "@esbuild/aix-ppc64": "0.25.4", + "@esbuild/android-arm": "0.25.4", + "@esbuild/android-arm64": "0.25.4", + "@esbuild/android-x64": "0.25.4", + "@esbuild/darwin-arm64": "0.25.4", + "@esbuild/darwin-x64": "0.25.4", + "@esbuild/freebsd-arm64": "0.25.4", + "@esbuild/freebsd-x64": "0.25.4", + "@esbuild/linux-arm": "0.25.4", + "@esbuild/linux-arm64": "0.25.4", + "@esbuild/linux-ia32": "0.25.4", + "@esbuild/linux-loong64": "0.25.4", + "@esbuild/linux-mips64el": "0.25.4", + "@esbuild/linux-ppc64": "0.25.4", + "@esbuild/linux-riscv64": "0.25.4", + "@esbuild/linux-s390x": "0.25.4", + "@esbuild/linux-x64": "0.25.4", + "@esbuild/netbsd-arm64": "0.25.4", + "@esbuild/netbsd-x64": "0.25.4", + "@esbuild/openbsd-arm64": "0.25.4", + "@esbuild/openbsd-x64": "0.25.4", + "@esbuild/sunos-x64": "0.25.4", + "@esbuild/win32-arm64": "0.25.4", + "@esbuild/win32-ia32": "0.25.4", + "@esbuild/win32-x64": "0.25.4" } }, "node_modules/escalade": { @@ -9641,60 +10347,64 @@ } }, "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "version": "9.27.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz", + "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.14.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.27.0", + "@eslint/plugin-kit": "^0.3.1", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.3.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-airbnb": { @@ -10036,6 +10746,19 @@ "node": ">= 0.4" } }, + "node_modules/eslint-config-erb/node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-config-erb/node_modules/eslint-plugin-jest": { "version": "27.9.0", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", @@ -10127,6 +10850,19 @@ "semver": "bin/semver.js" } }, + "node_modules/eslint-config-erb/node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, "node_modules/eslint-config-erb/node_modules/language-tags": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", @@ -10154,14 +10890,17 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", + "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", "dev": true, "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, "peerDependencies": { "eslint": ">=7.0.0" } @@ -10424,19 +11163,6 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint-plugin-import/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -10539,10 +11265,171 @@ "node": "*" } }, + "node_modules/eslint-plugin-perfectionist": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.13.0.tgz", + "integrity": "sha512-dsPwXwV7IrG26PJ+h1crQ1f5kxay/gQAU0NJnbVTQc91l5Mz9kPjyIZ7fXgie+QSgi8a+0TwGbfaJx+GIhzuoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "^8.32.1", + "@typescript-eslint/utils": "^8.32.1", + "natural-orderby": "^5.0.0" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "eslint": ">=8.45.0" + } + }, + "node_modules/eslint-plugin-perfectionist/node_modules/@typescript-eslint/scope-manager": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-perfectionist/node_modules/@typescript-eslint/types": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-perfectionist/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/eslint-plugin-perfectionist/node_modules/@typescript-eslint/utils": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/eslint-plugin-perfectionist/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-perfectionist/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-perfectionist/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/eslint-plugin-perfectionist/node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.6.tgz", - "integrity": "sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.0.tgz", + "integrity": "sha512-BvQOvUhkVQM1i63iMETK9Hjud9QhqBnbtT1Zc642p9ynzBuCe5pybkOnvqZIBypXmMlsGcnU4HZ8sCTPfpAexA==", "dev": true, "license": "MIT", "dependencies": { @@ -10620,16 +11507,26 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.20", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", + "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { @@ -10643,19 +11540,6 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint-plugin-react/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -10820,9 +11704,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10830,26 +11714,23 @@ "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/minimatch": { @@ -10865,32 +11746,32 @@ "node": "*" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -10973,6 +11854,21 @@ "node": ">= 0.6" } }, + "node_modules/event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", + "license": "MIT", + "dependencies": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -11297,17 +12193,32 @@ "pend": "~1.2.0" } }, + "node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-loader": { @@ -11331,6 +12242,13 @@ "webpack": "^4.0.0 || ^5.0.0" } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT", + "optional": true + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -11341,6 +12259,19 @@ "minimatch": "^5.0.1" } }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -11424,18 +12355,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -11485,6 +12415,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, "license": "ISC", "dependencies": { "cross-spawn": "^7.0.6", @@ -11501,6 +12432,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "license": "ISC", "engines": { "node": ">=14" @@ -11577,6 +12509,12 @@ "node": ">= 0.6" } }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", + "license": "MIT" + }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -11747,7 +12685,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11762,6 +12699,27 @@ "node": ">=10" } }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -11946,6 +12904,19 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/global-agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", @@ -12007,12 +12978,16 @@ } }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", + "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", + "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globalthis": { @@ -12198,7 +13173,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -12250,6 +13224,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true, + "license": "ISC" + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -12317,6 +13298,15 @@ "dev": true, "license": "MIT" }, + "node_modules/hexy": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.2.11.tgz", + "integrity": "sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==", + "license": "MIT", + "bin": { + "hexy": "bin/hexy_cmd.js" + } + }, "node_modules/history": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", @@ -12572,7 +13562,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", - "dev": true, "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -12588,20 +13577,10 @@ "entities": "^4.5.0" } }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "dev": true, "license": "BSD-2-Clause" }, @@ -12652,18 +13631,17 @@ } }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "license": "MIT", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/http-proxy-middleware": { @@ -12719,17 +13697,17 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "6", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/human-signals": { @@ -12917,7 +13895,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -12940,9 +13917,9 @@ } }, "node_modules/idb-keyval": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", - "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", + "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", "license": "Apache-2.0" }, "node_modules/identity-obj-proxy": { @@ -13007,9 +13984,9 @@ } }, "node_modules/immutable": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.1.tgz", - "integrity": "sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.2.tgz", + "integrity": "sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==", "dev": true, "license": "MIT" }, @@ -13188,7 +14165,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -13360,7 +14336,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -13425,6 +14400,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -13548,16 +14524,6 @@ "node": ">=8" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -13592,7 +14558,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -13825,6 +14790,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, "license": "ISC" }, "node_modules/isobject": { @@ -14790,6 +15756,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbi": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-2.0.5.tgz", + "integrity": "sha512-TzO/62Hxeb26QMb4IGlI/5X+QLr9Uqp1FPkwp2+KOICW+Q+vSuFj61c8pkT6wAns4WcK56X7CmSHhJeDGWOqxQ==" + }, "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", @@ -14844,14 +15815,17 @@ } } }, - "node_modules/jsdom/node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "node_modules/jsdom/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "license": "MIT", + "dependencies": { + "debug": "4" + }, "engines": { - "node": ">= 6" + "node": ">= 6.0.0" } }, "node_modules/jsdom/node_modules/form-data": { @@ -14885,6 +15859,20 @@ "node": ">= 6" } }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/jsdom/node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -15623,6 +16611,12 @@ "node": ">=8" } }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -15676,118 +16670,19 @@ } }, "node_modules/magic-bytes.js": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.11.0.tgz", - "integrity": "sha512-nVmadqN9gam80tdnn74qjFCKgldwzv1+96XmeCvR3bY7wNn2PjHMnRakOWC6+32g133vgZOjUiYgswIxohffzA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.12.1.tgz", + "integrity": "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==", + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, "license": "MIT", "dependencies": { - "rimraf": "^6.0.1" - } - }, - "node_modules/magic-bytes.js/node_modules/glob": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz", - "integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/magic-bytes.js/node_modules/jackspeak": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz", - "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/magic-bytes.js/node_modules/lru-cache": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", - "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/magic-bytes.js/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/magic-bytes.js/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/magic-bytes.js/node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/magic-bytes.js/node_modules/rimraf": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", - "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", - "license": "ISC", - "dependencies": { - "glob": "^11.0.0", - "package-json-from-dist": "^1.0.0" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/make-dir": { @@ -15841,6 +16736,58 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/make-fetch-happen/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/make-fetch-happen/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -15874,6 +16821,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==" + }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -16286,16 +17238,19 @@ "license": "ISC" }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -16482,6 +17437,17 @@ "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==", "license": "MIT" }, + "node_modules/mpris-service": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mpris-service/-/mpris-service-2.1.2.tgz", + "integrity": "sha512-AC6WepCnFWwOME9OWplHZ8ps/BB+g9QrEpUKCv7wX82fDPzR3nPrypOFmL/Fm0JloEAu6QTWSfDLLc6mM/jinw==", + "license": "MIT", + "dependencies": { + "dbus-next": "^0.9.2", + "deep-equal": "^1.0.1", + "source-map-support": "^0.5.11" + } + }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -16512,6 +17478,13 @@ "multicast-dns": "cli.js" } }, + "node_modules/nan": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz", + "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==", + "license": "MIT", + "optional": true + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -16544,6 +17517,16 @@ "dev": true, "license": "MIT" }, + "node_modules/natural-orderby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz", + "integrity": "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/negotiator": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", @@ -16579,9 +17562,9 @@ } }, "node_modules/node-abi": { - "version": "3.74.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz", - "integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==", + "version": "3.75.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", + "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", "dev": true, "license": "MIT", "dependencies": { @@ -16619,6 +17602,78 @@ "node": ">= 6.13.0" } }, + "node_modules/node-gyp": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/node-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -16719,11 +17774,27 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0" @@ -16765,7 +17836,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", @@ -16782,7 +17852,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -17013,9 +18082,9 @@ } }, "node_modules/overlayscrollbars": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.11.1.tgz", - "integrity": "sha512-kogaNaBTIizRenQ2GTzt2cpkEH9B0nUBXseRxqQblH/YicJ3TaWuvn8E5TXPPfJCVoHYSgBYZzzva40kCERKHg==", + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.11.3.tgz", + "integrity": "sha512-8frVuHyBEOoWlO8VPlp7N+5XI1IrMkzWFR4GjPaTlvjdHQ+XN1C+hMQJpIy0QK1jMAK/cSLVRPG0jirqX0gA0A==", "license": "MIT" }, "node_modules/overlayscrollbars-react": { @@ -17141,6 +18210,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, "license": "BlueOak-1.0.0" }, "node_modules/pako": { @@ -17195,7 +18265,6 @@ "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, "license": "MIT", "dependencies": { "entities": "^6.0.0" @@ -17208,7 +18277,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", - "dev": true, "license": "MIT", "dependencies": { "domhandler": "^5.0.3", @@ -17222,7 +18290,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", - "dev": true, "license": "MIT", "dependencies": { "parse5": "^7.0.0" @@ -17232,11 +18299,13 @@ } }, "node_modules/parse5/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", + "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -17286,6 +18355,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -17354,6 +18424,33 @@ "node": ">=8" } }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", + "license": [ + "MIT", + "Apache2" + ], + "dependencies": { + "through": "~2.3" + } + }, + "node_modules/pe-library": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz", + "integrity": "sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jet2jet" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -18673,28 +19770,26 @@ } }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "dev": true, "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "dev": true, "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "scheduler": "^0.26.0" }, "peerDependencies": { - "react": "^18.3.1" + "react": "^19.1.0" } }, "node_modules/react-error-boundary": { @@ -18800,9 +19895,9 @@ } }, "node_modules/react-remove-scroll": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", - "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.0.tgz", + "integrity": "sha512-sGsQtcjMqdQyijAHytfGEELB8FufGbfXIsvUTe+NLx1GDRJCXtCFLBLUI1eyZCKXXvbEU2C6gai0PZKoIE9Vbg==", "license": "MIT", "dependencies": { "react-remove-scroll-bar": "^2.3.7", @@ -18946,6 +20041,16 @@ "dev": true, "license": "MIT" }, + "node_modules/react-test-renderer/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/react-textarea-autosize": { "version": "8.3.4", "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.4.tgz", @@ -19038,24 +20143,6 @@ "read-binary-file-arch": "cli.js" } }, - "node_modules/read-config-file": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", - "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "config-file-ts": "^0.2.4", - "dotenv": "^9.0.2", - "dotenv-expand": "^5.1.0", - "js-yaml": "^4.1.0", - "json5": "^2.2.0", - "lazy-val": "^1.0.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/read-pkg": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", @@ -19198,17 +20285,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "license": "MIT" - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", @@ -19401,6 +20481,24 @@ "dev": true, "license": "MIT" }, + "node_modules/resedit": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.2.tgz", + "integrity": "sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pe-library": "^0.4.1" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jet2jet" + } + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -19630,6 +20728,46 @@ "node": ">=8.0" } }, + "node_modules/rollup": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.0.tgz", + "integrity": "sha512-HqMFpUbWlf/tvcxBFNKnJyzc7Lk+XO3FGc3pbNBLqEbOz0gPLRgcrlS3UF4MfUrVlstOaP/q0kM6GVvi+LrLRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.7" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.41.0", + "@rollup/rollup-android-arm64": "4.41.0", + "@rollup/rollup-darwin-arm64": "4.41.0", + "@rollup/rollup-darwin-x64": "4.41.0", + "@rollup/rollup-freebsd-arm64": "4.41.0", + "@rollup/rollup-freebsd-x64": "4.41.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.41.0", + "@rollup/rollup-linux-arm-musleabihf": "4.41.0", + "@rollup/rollup-linux-arm64-gnu": "4.41.0", + "@rollup/rollup-linux-arm64-musl": "4.41.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.41.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.41.0", + "@rollup/rollup-linux-riscv64-gnu": "4.41.0", + "@rollup/rollup-linux-riscv64-musl": "4.41.0", + "@rollup/rollup-linux-s390x-gnu": "4.41.0", + "@rollup/rollup-linux-x64-gnu": "4.41.0", + "@rollup/rollup-linux-x64-musl": "4.41.0", + "@rollup/rollup-win32-arm64-msvc": "4.41.0", + "@rollup/rollup-win32-ia32-msvc": "4.41.0", + "@rollup/rollup-win32-x64-msvc": "4.41.0", + "fsevents": "~2.3.2" + } + }, "node_modules/rsvp": { "version": "4.8.5", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", @@ -19708,7 +20846,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -19764,7 +20901,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, "license": "MIT" }, "node_modules/sanitize-filename": { @@ -19778,9 +20914,9 @@ } }, "node_modules/sass": { - "version": "1.87.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.87.0.tgz", - "integrity": "sha512-d0NoFH4v6SjEK7BoX810Jsrhj7IQSYHAHLi/iSpgqKc7LaIDshFRlSg5LOymf9FqQhxEHs2W5ZQXlvy0KD45Uw==", + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.0.tgz", + "integrity": "sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==", "dev": true, "license": "MIT", "dependencies": { @@ -19798,6 +20934,407 @@ "@parcel/watcher": "^2.4.1" } }, + "node_modules/sass-embedded": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.89.0.tgz", + "integrity": "sha512-EDrK1el9zdgJFpocCGlxatDWaP18tJBWoM1hxzo2KJBvjdmBichXI6O6KlQrigvQPO3uJ8DfmFmAAx7s7CG6uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.0.0", + "buffer-builder": "^0.2.0", + "colorjs.io": "^0.5.0", + "immutable": "^5.0.2", + "rxjs": "^7.4.0", + "supports-color": "^8.1.1", + "sync-child-process": "^1.0.2", + "varint": "^6.0.0" + }, + "bin": { + "sass": "dist/bin/sass.js" + }, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "sass-embedded-android-arm": "1.89.0", + "sass-embedded-android-arm64": "1.89.0", + "sass-embedded-android-ia32": "1.89.0", + "sass-embedded-android-riscv64": "1.89.0", + "sass-embedded-android-x64": "1.89.0", + "sass-embedded-darwin-arm64": "1.89.0", + "sass-embedded-darwin-x64": "1.89.0", + "sass-embedded-linux-arm": "1.89.0", + "sass-embedded-linux-arm64": "1.89.0", + "sass-embedded-linux-ia32": "1.89.0", + "sass-embedded-linux-musl-arm": "1.89.0", + "sass-embedded-linux-musl-arm64": "1.89.0", + "sass-embedded-linux-musl-ia32": "1.89.0", + "sass-embedded-linux-musl-riscv64": "1.89.0", + "sass-embedded-linux-musl-x64": "1.89.0", + "sass-embedded-linux-riscv64": "1.89.0", + "sass-embedded-linux-x64": "1.89.0", + "sass-embedded-win32-arm64": "1.89.0", + "sass-embedded-win32-ia32": "1.89.0", + "sass-embedded-win32-x64": "1.89.0" + } + }, + "node_modules/sass-embedded-android-arm": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.89.0.tgz", + "integrity": "sha512-s6jxkEZQQrtyIGZX6Sbcu7tEixFG2VkqFgrX11flm/jZex7KaxnZtFace+wnYAgHqzzYpx0kNzJUpT+GXxm8CA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-arm64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.89.0.tgz", + "integrity": "sha512-pr4R3p5R+Ul9ZA5nzYbBJQFJXW6dMGzgpNBhmaToYDgDhmNX5kg0mZAUlGLHvisLdTiR6oEfDDr9QI6tnD2nqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-ia32": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.89.0.tgz", + "integrity": "sha512-GoNnNGYmp1F0ZMHqQbAurlQsjBMZKtDd5H60Ruq86uQFdnuNqQ9wHKJsJABxMnjfAn60IjefytM5PYTMcAmbfA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-riscv64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.89.0.tgz", + "integrity": "sha512-di+i4KkKAWTNksaQYTqBEERv46qV/tvv14TPswEfak7vcTQ2pj2mvV4KGjLYfU2LqRkX/NTXix9KFthrzFN51Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-x64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.89.0.tgz", + "integrity": "sha512-1cRRDAnmAS1wLaxfFf6PCHu9sKW8FNxdM7ZkanwxO9mztrCu/uvfqTmaurY9+RaKvPus7sGYFp46/TNtl/wRjg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-arm64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.89.0.tgz", + "integrity": "sha512-EUNUzI0UkbQ6dASPyf09S3x7fNT54PjyD594ZGTY14Yh4qTuacIj27ckLmreAJNNu5QxlbhyYuOtz+XN5bMMxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-x64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.89.0.tgz", + "integrity": "sha512-23R8zSuB31Fq/MYpmQ38UR2C26BsYb66VVpJgWmWl/N+sgv/+l9ECuSPMbYNgM3vb9TP9wk9dgL6KkiCS5tAyg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.89.0.tgz", + "integrity": "sha512-KAzA1XD74d8/fiJXxVnLfFwfpmD2XqUJZz+DL6ZAPNLH1sb+yCP7brktaOyClDc/MBu61JERdHaJjIZhfX0Yqw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.89.0.tgz", + "integrity": "sha512-g9Lp57qyx51ttKj0AN/edV43Hu1fBObvD7LpYwVfs6u3I95r0Adi90KujzNrUqXxJVmsfUwseY8kA8zvcRjhYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-ia32": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.89.0.tgz", + "integrity": "sha512-5fxBeXyvBr3pb+vyrx9V6yd7QDRXkAPbwmFVVhjqshBABOXelLysEFea7xokh/tM8JAAQ4O8Ls3eW3Eojb477g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.89.0.tgz", + "integrity": "sha512-0Q1JeEU4/tzH7fwAwarfIh+Swn3aXG/jPhVsZpbR1c1VzkeaPngmXdmLJcVXsdb35tjk84DuYcFtJlE1HYGw4Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.89.0.tgz", + "integrity": "sha512-50oelrOtN64u15vJN9uJryIuT0+UPjyeoq0zdWbY8F7LM9294Wf+Idea+nqDUWDCj1MHndyPFmR1mjeuRouJhw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-ia32": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.89.0.tgz", + "integrity": "sha512-ILWqpTd+0RdsSw977iVAJf4CLetIbcQgLQf17ycS1N4StZKVRZs1bBfZhg/f/HU/4p5HondPAwepgJepZZdnFA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-riscv64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.89.0.tgz", + "integrity": "sha512-n2V+Tdjj7SAuiuElJYhWiHjjB1YU0cuFvL1/m5K+ecdNStfHFWIzvBT6/vzQnBOWjI4eZECNVuQ8GwGWCufZew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-x64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.89.0.tgz", + "integrity": "sha512-KOHJdouBK3SLJKZLnFYzuxs3dn+6jaeO3p4p1JUYAcVfndcvh13Sg2sLGfOfpg7Og6ws2Nnqnx0CyL26jPJ7ag==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-riscv64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.89.0.tgz", + "integrity": "sha512-0A/UWeKX6MYhVLWLkdX3NPKHO+mvIwzaf6TxGCy3vS3TODWaeDUeBhHShAr7YlOKv5xRGxf7Gx7FXCPV0mUyMA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-x64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.89.0.tgz", + "integrity": "sha512-dRBoOFPDWctHPYK3hTk3YzyX/icVrXiw7oOjbtpaDr6JooqIWBe16FslkWyvQzdmfOFy80raKVjgoqT7DsznkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-win32-arm64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.89.0.tgz", + "integrity": "sha512-RnlVZ14hC/W7ubzvhqnbGfjU5PFNoFP/y5qycgCy+Mezb0IKbWvZ2Lyzux8TbL3OIjOikkNpfXoNQrX706WLAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-win32-ia32": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.89.0.tgz", + "integrity": "sha512-eFe9VMNG+90nuoE3eXDy+38+uEHGf7xcqalq5+0PVZfR+H9RlaEbvIUNflZV94+LOH8Jb4lrfuekhHgWDJLfSg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-win32-x64": { + "version": "1.89.0", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.89.0.tgz", + "integrity": "sha512-AaGpr5R6MLCuSvkvDdRq49ebifwLcuGPk0/10hbYw9nh3jpy2/CylYubQpIpR4yPcuD1wFwFqufTXC3HJYGb0g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/sass-loader": { "version": "12.6.0", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", @@ -19857,13 +21394,11 @@ } }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "dev": true, + "license": "MIT" }, "node_modules/schema-utils": { "version": "3.3.0", @@ -19906,9 +21441,9 @@ } }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -20133,11 +21668,17 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -20155,7 +21696,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -20219,6 +21759,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -20231,6 +21772,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -20445,6 +21987,19 @@ "node": ">= 10" } }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/sort-keys": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.1.0.tgz", @@ -20483,7 +22038,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -20494,7 +22048,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -20574,6 +22127,18 @@ "wbuf": "^1.7.3" } }, + "node_modules/split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", + "license": "MIT", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -20672,6 +22237,15 @@ "node": ">= 0.4" } }, + "node_modules/stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", + "license": "MIT", + "dependencies": { + "duplexer": "~0.1.1" + } + }, "node_modules/stream-composer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz", @@ -20734,6 +22308,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -20749,6 +22324,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -20763,12 +22339,14 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, "license": "MIT" }, "node_modules/string-width/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, "license": "MIT" }, "node_modules/string.prototype.includes": { @@ -20888,6 +22466,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -20901,6 +22480,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -20980,9 +22560,9 @@ "license": "ISC" }, "node_modules/styled-components": { - "version": "6.1.17", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.17.tgz", - "integrity": "sha512-97D7DwWanI7nN24v0D4SvbfjLE9656umNSJZkBkDIWL37aZqG/wRQ+Y9pWtXyBIM/NSfcBzHLErEsqHmJNSVUg==", + "version": "6.1.18", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.18.tgz", + "integrity": "sha512-Mvf3gJFzZCkhjY2Y/Fx9z1m3dxbza0uI9H1CbNZm/jSHCojzJhQ0R7bByrlFJINnMzz/gPulpoFFGymNwrsMcw==", "license": "MIT", "dependencies": { "@emotion/is-prop-valid": "1.2.2", @@ -21284,17 +22864,17 @@ } }, "node_modules/stylelint-scss": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.11.1.tgz", - "integrity": "sha512-e4rYo0UY+BIMtGeGanghrvHTjcryxgZbyFxUedp8dLFqC4P70aawNdYjRrQxbnKhu3BNr4+lt5e/53tcKXiwFA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.12.0.tgz", + "integrity": "sha512-U7CKhi1YNkM1pXUXl/GMUXi8xKdhl4Ayxdyceie1nZ1XNIdaUgMV6OArpooWcDzEggwgYD0HP/xIgVJo9a655w==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "css-tree": "^3.0.1", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.35.0", - "mdn-data": "^2.15.0", + "known-css-properties": "^0.36.0", + "mdn-data": "^2.21.0", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.6", "postcss-selector-parser": "^7.1.0", @@ -21331,9 +22911,9 @@ "optional": true }, "node_modules/stylelint-scss/node_modules/known-css-properties": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz", - "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==", + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.36.0.tgz", + "integrity": "sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA==", "dev": true, "license": "MIT", "optional": true @@ -21408,6 +22988,21 @@ "node": ">=12.0.0" } }, + "node_modules/stylelint/node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/stylelint/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -21696,15 +23291,37 @@ "dev": true, "license": "MIT" }, - "node_modules/synckit": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.4.tgz", - "integrity": "sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==", + "node_modules/sync-child-process": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", + "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.3", - "tslib": "^2.8.1" + "sync-message-port": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/sync-message-port": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", + "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/synckit": { + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.6.tgz", + "integrity": "sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.4" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -21876,14 +23493,14 @@ } }, "node_modules/terser": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", - "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", + "version": "5.39.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.2.tgz", + "integrity": "sha512-yEPUmWve+VA78bI71BW70Dh0TuV4HHd+I5SHOAfS1+QBOmvmCiiffgjR8ryyEd3KIfvPGFqoADt8LdQ6XpXIvg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.14.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -22064,13 +23681,6 @@ "b4a": "^1.6.4" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, "node_modules/throat": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", @@ -22082,7 +23692,6 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, "license": "MIT" }, "node_modules/through2": { @@ -22149,6 +23758,36 @@ "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -22574,9 +24213,9 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", - "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", + "version": "4.19.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", + "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -22744,724 +24383,130 @@ "node": ">=14.17" } }, - "node_modules/typescript-plugin-styled-components": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/typescript-plugin-styled-components/-/typescript-plugin-styled-components-3.0.0.tgz", - "integrity": "sha512-QWlhTl6NqsFxtJyxn7pJjm3RhgzXSByUftZ3AoQClrMMpa4yAaHuJKTN1gFpH3Ti+Rwm56fNUfG9pXSBU+WW3A==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "typescript": "~4.8 || 5" - } - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "node_modules/typescript-eslint": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz", + "integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" + "@typescript-eslint/eslint-plugin": "8.32.1", + "@typescript-eslint/parser": "8.32.1", + "@typescript-eslint/utils": "8.32.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/underscore.string": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz", - "integrity": "sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "^1.1.1", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/undici": { - "version": "6.21.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", - "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unixify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", - "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "normalize-path": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unixify/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/unzip-crx-3": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/unzip-crx-3/-/unzip-crx-3-0.2.0.tgz", - "integrity": "sha512-0+JiUq/z7faJ6oifVB5nSwt589v1KCduqIJupNVDoWSXZtWDmjDGO3RAEOvwJ07w90aoXoP4enKsR7ecMrJtWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "jszip": "^3.1.0", - "mkdirp": "^0.5.1", - "yaku": "^0.16.6" - } - }, - "node_modules/unzip-crx-3/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-loader": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", - "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "loader-utils": "^2.0.0", - "mime-types": "^2.1.27", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "file-loader": "*", - "webpack": "^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "file-loader": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", + "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", "dev": true, "license": "MIT", "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/use-callback-ref": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", - "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/type-utils": "8.32.1", + "@typescript-eslint/utils": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/use-composed-ref": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", - "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-isomorphic-layout-effect": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz", - "integrity": "sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-latest": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", - "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz", + "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", + "dev": true, "license": "MIT", "dependencies": { - "use-isomorphic-layout-effect": "^1.1.1" + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/use-sidecar": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", - "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", + "dev": true, "license": "MIT", "dependencies": { - "detect-node-es": "^1.1.0", - "tslib": "^2.0.0" + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", + "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/utils": "8.32.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/use-sync-external-store": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", - "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/utf8-byte-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", - "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", - "dev": true, - "license": "(WTFPL OR MIT)" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true, - "license": "MIT" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "license": "MIT" - }, - "node_modules/v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", - "dev": true, - "license": "ISC", - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-or-function": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", - "integrity": "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/verror": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", - "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/vinyl": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", - "integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^2.1.2", - "clone-stats": "^1.0.0", - "remove-trailing-separator": "^1.1.0", - "replace-ext": "^2.0.0", - "teex": "^1.0.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/vinyl-contents": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", - "integrity": "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^5.0.0", - "vinyl": "^3.0.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/vinyl-contents/node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/vinyl-contents/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/vinyl-fs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-4.0.0.tgz", - "integrity": "sha512-7GbgBnYfaquMk3Qu9g22x000vbYkOex32930rBnc3qByw6HfMEAoELjCjoJv4HuEQxHAurT+nvMHm6MnJllFLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fs-mkdirp-stream": "^2.0.1", - "glob-stream": "^8.0.0", - "graceful-fs": "^4.2.11", - "iconv-lite": "^0.6.3", - "is-valid-glob": "^1.0.0", - "lead": "^4.0.0", - "normalize-path": "3.0.0", - "resolve-options": "^2.0.0", - "stream-composer": "^1.0.2", - "streamx": "^2.14.0", - "to-through": "^3.0.0", - "value-or-function": "^4.0.0", - "vinyl": "^3.0.0", - "vinyl-sourcemap": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz", - "integrity": "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "convert-source-map": "^2.0.0", - "graceful-fs": "^4.2.10", - "now-and-later": "^3.0.0", - "streamx": "^2.12.5", - "vinyl": "^3.0.0", - "vinyl-contents": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/vinyl-sourcemap/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/void-elements": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", - "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", - "dev": true, - "license": "MIT", - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/walk-sync": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/walk-sync/-/walk-sync-2.2.0.tgz", - "integrity": "sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimatch": "^3.0.3", - "ensure-posix-path": "^1.1.0", - "matcher-collection": "^2.0.0", - "minimatch": "^3.0.4" - }, - "engines": { - "node": "8.* || >= 10.*" - } - }, - "node_modules/walk-sync/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/walk-sync/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/watchboy": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/watchboy/-/watchboy-0.4.3.tgz", - "integrity": "sha512-GHs1HxwvxSMBsqd/WfTOZhj5gBdMqf5HQpfgtKxDfZRxrlYPDdVLRB61LCeRzJaWANmvSIMlfmRVDwVmJFgAKA==", - "dev": true, - "license": "ISC", - "dependencies": { - "lodash.difference": "^4.5.0", - "micromatch": "^4.0.2", - "pify": "^4.0.1", - "unixify": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=10.4" - } - }, - "node_modules/webpack": { - "version": "5.99.7", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.7.tgz", - "integrity": "sha512-CNqKBRMQjwcmKR0idID5va1qlhrqVUKpovi+Ec79ksW8ux7iS1+A6VqzfZXgVYCFRKl7XL5ap3ZoMpwBJxcg0w==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", "dev": true, "license": "MIT", "dependencies": { @@ -39594,415 +40639,661 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==" }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" } }, - "typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", "dev": true, - "requires": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", "dev": true, - "requires": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.1", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "node_modules/typescript-eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, - "requires": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "node_modules/typescript-eslint/node_modules/ignore": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", "dev": true, - "requires": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" + "license": "MIT", + "engines": { + "node": ">= 4" } }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/typescript-eslint/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "requires": { - "is-typedarray": "^1.0.0" + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true + "node_modules/typescript-eslint/node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } }, - "typescript-plugin-styled-components": { + "node_modules/typescript-plugin-styled-components": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/typescript-plugin-styled-components/-/typescript-plugin-styled-components-3.0.0.tgz", "integrity": "sha512-QWlhTl6NqsFxtJyxn7pJjm3RhgzXSByUftZ3AoQClrMMpa4yAaHuJKTN1gFpH3Ti+Rwm56fNUfG9pXSBU+WW3A==", - "dev": true + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": "~4.8 || 5" + } }, - "unbox-primitive": { + "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "underscore.string": { + "node_modules/underscore.string": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz", "integrity": "sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "sprintf-js": "^1.1.1", "util-deprecate": "^1.0.2" + }, + "engines": { + "node": "*" } }, - "undici": { + "node_modules/undici": { "version": "6.21.1", "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", - "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==" + "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } }, - "undici-types": { + "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true + "dev": true, + "license": "MIT" }, - "unique-filename": { + "node_modules/unique-filename": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, - "requires": { + "license": "ISC", + "dependencies": { "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "unique-slug": { + "node_modules/unique-slug": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, - "requires": { + "license": "ISC", + "dependencies": { "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "universalify": { + "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } }, - "unixify": { + "node_modules/unixify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "normalize-path": "^2.1.1" }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } + "engines": { + "node": ">=0.10.0" } }, - "unpipe": { + "node_modules/unixify/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "unzip-crx-3": { + "node_modules/unzip-crx-3": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/unzip-crx-3/-/unzip-crx-3-0.2.0.tgz", "integrity": "sha512-0+JiUq/z7faJ6oifVB5nSwt589v1KCduqIJupNVDoWSXZtWDmjDGO3RAEOvwJ07w90aoXoP4enKsR7ecMrJtWQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "jszip": "^3.1.0", "mkdirp": "^0.5.1", "yaku": "^0.16.6" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - } } }, - "update-browserslist-db": { + "node_modules/unzip-crx-3/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, - "requires": { + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "uri-js": { + "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "dependencies": { "punycode": "^2.1.0" } }, - "url-loader": { + "node_modules/url-loader": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "loader-utils": "^2.0.0", "mime-types": "^2.1.27", "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } } }, - "url-parse": { + "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, - "use-callback-ref": { + "node_modules/use-callback-ref": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", - "requires": { + "license": "MIT", + "dependencies": { "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "use-composed-ref": { + "node_modules/use-composed-ref": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", - "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==" + "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } }, - "use-isomorphic-layout-effect": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz", - "integrity": "sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==" + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", + "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } }, - "use-latest": { + "node_modules/use-latest": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", - "requires": { + "license": "MIT", + "dependencies": { "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "use-sidecar": { + "node_modules/use-sidecar": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", - "requires": { + "license": "MIT", + "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "use-sync-external-store": { + "node_modules/use-sync-external-store": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", - "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==" + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } }, - "utf8-byte-length": { + "node_modules/utf8-byte-length": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", - "dev": true + "dev": true, + "license": "(WTFPL OR MIT)" }, - "util-deprecate": { + "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "dev": true, + "license": "MIT" }, - "utila": { + "node_modules/utila": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true + "dev": true, + "license": "MIT" }, - "utils-merge": { + "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } }, - "uuid": { + "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } }, - "v8-compile-cache-lib": { + "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "dev": true, + "license": "MIT" }, - "v8-to-istanbul": { + "node_modules/v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", "dev": true, - "requires": { + "license": "ISC", + "dependencies": { "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0", "source-map": "^0.7.3" }, - "dependencies": { - "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true - } + "engines": { + "node": ">=10.12.0" } }, - "validate-npm-package-license": { + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "requires": { + "license": "Apache-2.0", + "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "value-or-function": { + "node_modules/value-or-function": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", "integrity": "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } }, - "vary": { + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "verror": { + "node_modules/verror": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", "dev": true, + "license": "MIT", "optional": true, - "requires": { + "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" } }, - "vinyl": { + "node_modules/vinyl": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", "integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "clone": "^2.1.2", "clone-stats": "^1.0.0", "remove-trailing-separator": "^1.1.0", "replace-ext": "^2.0.0", "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" } }, - "vinyl-contents": { + "node_modules/vinyl-contents": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", "integrity": "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "bl": "^5.0.0", "vinyl": "^3.0.0" }, - "dependencies": { - "bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "dev": true, - "requires": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - } + "engines": { + "node": ">=10.13.0" } }, - "vinyl-fs": { + "node_modules/vinyl-contents/node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/vinyl-contents/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/vinyl-fs": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-4.0.0.tgz", "integrity": "sha512-7GbgBnYfaquMk3Qu9g22x000vbYkOex32930rBnc3qByw6HfMEAoELjCjoJv4HuEQxHAurT+nvMHm6MnJllFLw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "fs-mkdirp-stream": "^2.0.1", "glob-stream": "^8.0.0", "graceful-fs": "^4.2.11", @@ -40017,14 +41308,18 @@ "value-or-function": "^4.0.0", "vinyl": "^3.0.0", "vinyl-sourcemap": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" } }, - "vinyl-sourcemap": { + "node_modules/vinyl-sourcemap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz", "integrity": "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "convert-source-map": "^2.0.0", "graceful-fs": "^4.2.10", "now-and-later": "^3.0.0", @@ -40032,132 +41327,255 @@ "vinyl": "^3.0.0", "vinyl-contents": "^2.0.0" }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-sourcemap/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "dev": true, + "license": "MIT", "dependencies": { - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, - "void-elements": { + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/void-elements": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", - "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==" + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "w3c-hr-time": { + "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "browser-process-hrtime": "^1.0.0" } }, - "w3c-xmlserializer": { + "node_modules/w3c-xmlserializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" } }, - "walk-sync": { + "node_modules/walk-sync": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/walk-sync/-/walk-sync-2.2.0.tgz", "integrity": "sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@types/minimatch": "^3.0.3", "ensure-posix-path": "^1.1.0", "matcher-collection": "^2.0.0", "minimatch": "^3.0.4" }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } + "engines": { + "node": "8.* || >= 10.*" } }, - "walker": { + "node_modules/walk-sync/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/walk-sync/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, - "requires": { + "license": "Apache-2.0", + "dependencies": { "makeerror": "1.0.12" } }, - "watchboy": { + "node_modules/watchboy": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/watchboy/-/watchboy-0.4.3.tgz", "integrity": "sha512-GHs1HxwvxSMBsqd/WfTOZhj5gBdMqf5HQpfgtKxDfZRxrlYPDdVLRB61LCeRzJaWANmvSIMlfmRVDwVmJFgAKA==", "dev": true, - "requires": { + "license": "ISC", + "dependencies": { "lodash.difference": "^4.5.0", "micromatch": "^4.0.2", "pify": "^4.0.1", "unixify": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "watchpack": { + "node_modules/watchpack": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" } }, - "wbuf": { + "node_modules/wbuf": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "minimalistic-assert": "^1.0.0" } }, - "wcwidth": { + "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "defaults": "^1.0.3" } }, - "webidl-conversions": { + "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "webpack": { - "version": "5.99.7", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.7.tgz", - "integrity": "sha512-CNqKBRMQjwcmKR0idID5va1qlhrqVUKpovi+Ec79ksW8ux7iS1+A6VqzfZXgVYCFRKl7XL5ap3ZoMpwBJxcg0w==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/webpack": { + "version": "5.99.8", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.8.tgz", + "integrity": "sha512-lQ3CPiSTpfOnrEGeXDwoq5hIGzSjmwD72GdfVzF7CQAI7t47rJG9eDWvcEkEn3CUQymAElVvDg3YNTlCYj+qUQ==", + "dev": true, + "license": "MIT", + "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", @@ -40183,64 +41601,29 @@ "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "enhanced-resolve": { - "version": "5.18.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", - "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true } } }, - "webpack-bundle-analyzer": { + "node_modules/webpack-bundle-analyzer": { "version": "4.10.2", "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@discoveryjs/json-ext": "0.5.7", "acorn": "^8.0.4", "acorn-walk": "^8.0.0", @@ -40254,36 +41637,65 @@ "sirv": "^2.0.3", "ws": "^7.3.1" }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", "dependencies": { - "acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "requires": { - "acorn": "^8.11.0" - } + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true }, - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true + "utf-8-validate": { + "optional": true } } }, - "webpack-cli": { + "node_modules/webpack-cli": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.2.0", "@webpack-cli/info": "^1.5.0", @@ -40297,81 +41709,142 @@ "rechoir": "^0.7.0", "webpack-merge": "^5.7.3" }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true }, - "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true } } }, - "webpack-dev-middleware": { + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-cli/node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/webpack-dev-middleware": { "version": "5.3.4", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.3", "mime-types": "^2.1.31", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "webpack-dev-server": { + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { "version": "4.15.2", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", "@types/express": "^4.17.13", @@ -40403,169 +41876,336 @@ "webpack-dev-middleware": "^5.3.4", "ws": "^8.13.0" }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } + "webpack-cli": { + "optional": true } } }, - "webpack-merge": { + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" } }, - "webpack-sources": { + "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } }, - "websocket-driver": { + "node_modules/webpack/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack/node_modules/enhanced-resolve": { + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", "dev": true, - "requires": { + "license": "Apache-2.0", + "dependencies": { "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" } }, - "websocket-extensions": { + "node_modules/websocket-extensions": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } }, - "whatwg-encoding": { + "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" } }, - "whatwg-mimetype": { + "node_modules/whatwg-mimetype": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true + "license": "MIT", + "engines": { + "node": ">=18" + } }, - "whatwg-url": { + "node_modules/whatwg-url": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "lodash": "^4.7.0", "tr46": "^2.1.0", "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" } }, - "which": { + "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { + "dev": true, + "license": "ISC", + "dependencies": { "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "which-boxed-primitive": { + "node_modules/which-boxed-primitive": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "which-builtin-type": { + "node_modules/which-builtin-type": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", @@ -40579,26 +42219,40 @@ "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "which-collection": { + "node_modules/which-collection": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "which-typed-array": { + "node_modules/which-typed-array": { "version": "1.1.19", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", @@ -40606,117 +42260,215 @@ "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "wildcard": { + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true + "dev": true, + "license": "MIT" }, - "word-wrap": { + "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "wrap-ansi": { + "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, - "write-file-atomic": { + "node_modules/write-file-atomic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, - "requires": { + "license": "ISC", + "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", "signal-exit": "^3.0.2", "typedarray-to-buffer": "^3.1.5" } }, - "ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==" + "node_modules/ws": { + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, - "xml-name-validator": { + "node_modules/xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, - "xmlbuilder": { + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } }, - "xmlchars": { + "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "dev": true, + "license": "MIT" }, - "xtend": { + "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } }, - "y18n": { + "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } }, - "yaku": { + "node_modules/yaku": { "version": "0.16.7", "resolved": "https://registry.npmjs.org/yaku/-/yaku-0.16.7.tgz", "integrity": "sha512-Syu3IB3rZvKvYk7yTiyl1bo/jiEFaaStrgv1V2TIJTqYPStSMQVO8EQjg/z+DRzLq/4LIIharNT3iH1hylEIRw==", - "dev": true + "dev": true, + "license": "MIT" }, - "yallist": { + "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, - "yaml": { + "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } }, - "yargs": { + "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", @@ -40725,54 +42477,99 @@ "y18n": "^5.0.5", "yargs-parser": "^21.1.1" }, - "dependencies": { - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } + "engines": { + "node": ">=12" } }, - "yargs-parser": { + "node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } }, - "yauzl": { + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, - "yn": { + "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "yocto-queue": { + "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "zod": { - "version": "3.24.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz", - "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==" + "node_modules/zod": { + "version": "3.24.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", + "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } }, - "zustand": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.6.tgz", - "integrity": "sha512-ibr/n1hBzLLj5Y+yUcU7dYw8p6WnIVzdJbnX+1YpaScvZVF2ziugqHs+LAmHw4lWO9c/zRj+K1ncgWDQuthEdQ==", - "requires": { + "node_modules/zustand": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", + "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", + "license": "MIT", + "dependencies": { "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } } } } diff --git a/package.json b/package.json index e1f66602..95786724 100644 --- a/package.json +++ b/package.json @@ -1,297 +1,25 @@ { "name": "feishin", - "productName": "Feishin", - "description": "Feishin music server", - "version": "0.13.0", + "version": "1.0.0", + "description": "An Electron application with React and TypeScript", + "main": "./out/main/index.js", + "author": "example.com", + "homepage": "https://electron-vite.org", "scripts": { - "build": "concurrently \"npm run build:main\" \"npm run build:renderer\" \"npm run build:remote\"", - "build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.prod.ts", - "build:remote": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.remote.prod.ts", - "build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts", - "build:web": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.web.prod.ts", - "build:docker": "docker build -t jeffvli/feishin .", - "rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app", - "lint": "concurrently \"npm run lint:code\" \"npm run lint:styles\"", - "lint:code": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx --fix", - "lint:styles": "npx stylelint **/*.tsx --fix", - "package": "node --import tsx ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never", - "package:pr": "node --import tsx ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never --win --mac --linux", - "package:pr:macos": "node --import tsx ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never --mac", - "package:pr:windows": "node --import tsx ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never --win", - "package:pr:linux": "node --import tsx ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never --linux", - "package:dev": "node --import tsx ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never --dir", - "postinstall": "node --import tsx .erb/scripts/check-native-dep.js && electron-builder install-app-deps && cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts", - "start": "node --import tsx ./.erb/scripts/check-port-in-use.js && npm run start:renderer", - "start:main": "cross-env NODE_ENV=development NODE_OPTIONS=\"--import tsx\" electron -r ts-node/register/transpile-only ./src/main/main.ts", - "start:preload": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.preload.dev.ts", - "start:remote": "cross-env NODE_ENV=developemnt TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.remote.dev.ts", - "start:renderer": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts", - "start:web": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./.erb/configs/webpack.config.renderer.web.ts", - "test": "jest", - "prepare": "husky install", - "i18next": "i18next -c src/i18n/i18next-parser.config.js", - "prod:buildserver": "pwsh -c \"./scripts/server-build.ps1\"", - "prod:publishserver": "pwsh -c \"./scripts/server-publish.ps1\"" - }, - "lint-staged": { - "*.{js,jsx,ts,tsx}": [ - "cross-env NODE_ENV=development eslint --cache" - ], - "*.json,.{eslintrc,prettierrc}": [ - "prettier --ignore-path .eslintignore --parser json --write" - ], - "*.{css,scss}": [ - "prettier --ignore-path .eslintignore --single-quote --write" - ], - "*.{html,md,yml}": [ - "prettier --ignore-path .eslintignore --single-quote --write" - ] - }, - "build": { - "productName": "Feishin", - "appId": "org.jeffvli.feishin", - "artifactName": "${productName}-${version}-${os}-${arch}.${ext}", - "asar": true, - "asarUnpack": "**\\*.{node,dll}", - "files": [ - "dist", - "node_modules", - "package.json" - ], - "afterSign": ".erb/scripts/notarize.js", - "electronVersion": "36.1.0", - "mac": { - "target": { - "target": "default", - "arch": [ - "arm64", - "x64" - ] - }, - "icon": "assets/icons/icon.icns", - "type": "distribution", - "hardenedRuntime": true, - "entitlements": "assets/entitlements.mac.plist", - "entitlementsInherit": "assets/entitlements.mac.plist", - "gatekeeperAssess": false - }, - "dmg": { - "contents": [ - { - "x": 130, - "y": 220 - }, - { - "x": 410, - "y": 220, - "type": "link", - "path": "/Applications" - } - ] - }, - "win": { - "target": [ - "nsis", - "zip" - ], - "icon": "assets/icons/icon.ico" - }, - "deb": { - "depends": [ - "libgssapi_krb5.so.2", - "libavahi-common.so.3", - "libavahi-client.so.3", - "libkrb5.so.3", - "libkrb5support.so.0", - "libkeyutils.so.1", - "libcups.so.2" - ] - }, - "rpm": { - "depends": [ - "libgssapi_krb5.so.2", - "libavahi-common.so.3", - "libavahi-client.so.3", - "libkrb5.so.3", - "libkrb5support.so.0", - "libkeyutils.so.1", - "libcups.so.2" - ] - }, - "freebsd": { - "depends": [ - "libgssapi_krb5.so.2", - "libavahi-common.so.3", - "libavahi-client.so.3", - "libkrb5.so.3", - "libkrb5support.so.0", - "libkeyutils.so.1", - "libcups.so.2" - ] - }, - "linux": { - "target": [ - "AppImage", - "tar.xz" - ], - "icon": "assets/icons/icon.png", - "category": "AudioVideo;Audio;Player" - }, - "directories": { - "app": "release/app", - "buildResources": "assets", - "output": "release/build" - }, - "extraResources": [ - "./assets/**" - ], - "publish": { - "provider": "github", - "owner": "jeffvli", - "repo": "feishin" - } - }, - "repository": { - "type": "git", - "url": "git+https://github.com/jeffvli/feishin.git" - }, - "author": { - "name": "jeffvli", - "url": "https://github.com/jeffvli/" - }, - "contributors": [], - "license": "GPL-3.0", - "bugs": { - "url": "https://github.com/jeffvli/feishin/issues" - }, - "keywords": [ - "subsonic", - "navidrome", - "airsonic", - "jellyfin", - "react", - "electron" - ], - "homepage": "https://github.com/jeffvli/feishin", - "jest": { - "testURL": "http://localhost/", - "testEnvironment": "jsdom", - "transform": { - "\\.(ts|tsx|js|jsx)$": "ts-jest" - }, - "moduleNameMapper": { - "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/.erb/mocks/fileMock.js", - "\\.(css|less|sass|scss)$": "identity-obj-proxy" - }, - "moduleFileExtensions": [ - "js", - "jsx", - "ts", - "tsx", - "json" - ], - "moduleDirectories": [ - "node_modules", - "release/app/node_modules" - ], - "testPathIgnorePatterns": [ - "release/app/dist" - ], - "setupFiles": [ - "./.erb/scripts/check-build-exists.ts" - ] - }, - "devDependencies": { - "@electron/rebuild": "^3.6.0", - "@pmmmwh/react-refresh-webpack-plugin": "0.5.5", - "@stylelint/postcss-css-in-js": "^0.38.0", - "@teamsupercell/typings-for-css-modules-loader": "^2.5.1", - "@testing-library/jest-dom": "^5.16.4", - "@testing-library/react": "^13.0.0", - "@types/dompurify": "^3.0.5", - "@types/electron-localshortcut": "^3.1.0", - "@types/jest": "^27.4.1", - "@types/lodash": "^4.14.188", - "@types/md5": "^2.3.2", - "@types/node": "^17.0.23", - "@types/react": "^18.0.25", - "@types/react-dom": "^18.0.8", - "@types/react-test-renderer": "^17.0.1", - "@types/react-virtualized-auto-sizer": "^1.0.1", - "@types/react-window": "^1.8.5", - "@types/react-window-infinite-loader": "^1.0.6", - "@types/styled-components": "^5.1.26", - "@types/terser-webpack-plugin": "^5.0.4", - "@types/webpack-bundle-analyzer": "^4.4.1", - "@types/webpack-env": "^1.16.3", - "@typescript-eslint/eslint-plugin": "^5.47.0", - "@typescript-eslint/parser": "^5.47.0", - "browserslist-config-erb": "^0.0.3", - "chalk": "^4.1.2", - "concurrently": "^7.1.0", - "core-js": "^3.21.1", - "cross-env": "^7.0.3", - "css-loader": "^6.7.1", - "css-minimizer-webpack-plugin": "^3.4.1", - "detect-port": "^1.3.0", - "electron": "^36.1.0", - "electron-builder": "^24.13.3", - "electron-devtools-installer": "^3.2.0", - "electron-notarize": "^1.2.1", - "electronmon": "^2.0.2", - "eslint": "^8.30.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-erb": "^4.0.3", - "eslint-import-resolver-typescript": "^2.7.1", - "eslint-import-resolver-webpack": "^0.13.2", - "eslint-plugin-compat": "^4.2.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jest": "^26.1.3", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-promise": "^6.0.0", - "eslint-plugin-react": "^7.29.4", - "eslint-plugin-react-hooks": "^4.4.0", - "eslint-plugin-sort-keys-fix": "^1.1.2", - "eslint-plugin-typescript-sort-keys": "^2.1.0", - "file-loader": "^6.2.0", - "html-webpack-plugin": "^5.5.0", - "husky": "^7.0.4", - "i18next-parser": "^9.0.2", - "identity-obj-proxy": "^3.0.0", - "jest": "^27.5.1", - "lint-staged": "^12.3.7", - "mini-css-extract-plugin": "^2.6.0", - "postcss-scss": "^4.0.4", - "postcss-styled-syntax": "^0.5.0", - "postcss-syntax": "^0.36.2", - "prettier": "^3.3.3", - "react-refresh": "^0.12.0", - "react-refresh-typescript": "^2.0.4", - "react-test-renderer": "^18.0.0", - "rimraf": "^3.0.2", - "sass": "^1.49.11", - "sass-loader": "^12.6.0", - "style-loader": "^3.3.1", - "stylelint": "^15.10.3", - "stylelint-config-css-modules": "^4.3.0", - "stylelint-config-recess-order": "^4.3.0", - "stylelint-config-standard": "^34.0.0", - "stylelint-config-standard-scss": "^4.0.0", - "stylelint-config-styled-components": "^0.1.1", - "terser-webpack-plugin": "^5.3.1", - "ts-jest": "^27.1.4", - "ts-loader": "^9.2.8", - "ts-node": "^10.9.2", - "tsconfig-paths-webpack-plugin": "^4.0.0", - "tsx": "^4.16.2", - "typescript": "^5.2.2", - "typescript-plugin-styled-components": "^3.0.0", - "url-loader": "^4.1.1", - "webpack": "^5.94.0", - "webpack-bundle-analyzer": "^4.5.0", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.8.0", - "webpack-merge": "^5.8.0" + "format": "prettier --write .", + "lint": "eslint --cache --fix .", + "typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false", + "typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false", + "typecheck": "npm run typecheck:node && npm run typecheck:web", + "start": "electron-vite preview", + "dev": "electron-vite dev", + "dev:watch": "electron-vite dev --watch", + "build": "npm run typecheck && electron-vite build", + "postinstall": "electron-builder install-app-deps", + "build:unpack": "npm run build && electron-builder --dir", + "build:win": "npm run build && electron-builder --win", + "build:mac": "electron-vite build && electron-builder --mac", + "build:linux": "electron-vite build && electron-builder --linux" }, "dependencies": { "@ag-grid-community/client-side-row-model": "^28.2.1", @@ -299,6 +27,8 @@ "@ag-grid-community/infinite-row-model": "^28.2.1", "@ag-grid-community/react": "^28.2.1", "@ag-grid-community/styles": "^28.2.1", + "@electron-toolkit/preload": "^3.0.1", + "@electron-toolkit/utils": "^4.0.0", "@emotion/react": "^11.10.4", "@mantine/core": "^6.0.17", "@mantine/dates": "^6.0.17", @@ -315,6 +45,7 @@ "audiomotion-analyzer": "^4.5.0", "auto-text-size": "^0.2.3", "axios": "^1.6.0", + "cheerio": "^1.0.0", "clsx": "^2.0.0", "cmdk": "^0.2.0", "dayjs": "^1.11.6", @@ -323,7 +54,7 @@ "electron-localshortcut": "^3.2.1", "electron-log": "^5.1.1", "electron-store": "^8.1.0", - "electron-updater": "^6.3.1", + "electron-updater": "^6.3.9", "fast-average-color": "^9.3.0", "format-duration": "^2.0.0", "framer-motion": "^11.0.0", @@ -336,11 +67,12 @@ "lodash": "^4.17.21", "md5": "^2.3.0", "memoize-one": "^6.0.0", + "mpris-service": "^2.1.2", "nanoid": "^3.3.3", "net": "^1.0.2", "node-mpv": "github:jeffvli/Node-MPV#32b4d64395289ad710c41d481d2707a7acfc228f", - "overlayscrollbars": "^2.2.1", - "overlayscrollbars-react": "^0.5.1", + "overlayscrollbars": "^2.11.1", + "overlayscrollbars-react": "^0.5.6", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", @@ -356,33 +88,112 @@ "semver": "^7.5.4", "styled-components": "^6.0.8", "swiper": "^9.3.1", + "ws": "^8.18.2", "zod": "^3.22.3", "zustand": "^4.3.9" }, - "resolutions": { - "styled-components": "^6", - "entities": "2.2.0" - }, - "overrides": { - "entities": "2.2.0" - }, - "devEngines": { - "runtime": { - "name": "node", - "version": ">=18.x", - "onFail": "error" - }, - "packageManager": { - "name": "npm", - "version": ">=7.x", - "onFail": "error" - } - }, - "browserslist": [], - "electronmon": { - "patterns": [ - "!server", - "!src/renderer" - ] + "devDependencies": { + "@electron-toolkit/eslint-config-prettier": "^3.0.0", + "@electron-toolkit/eslint-config-ts": "^3.0.0", + "@electron-toolkit/tsconfig": "^1.0.1", + "@electron/rebuild": "^3.6.0", + "@pmmmwh/react-refresh-webpack-plugin": "0.5.5", + "@stylelint/postcss-css-in-js": "^0.38.0", + "@teamsupercell/typings-for-css-modules-loader": "^2.5.1", + "@testing-library/jest-dom": "^5.16.4", + "@testing-library/react": "^13.0.0", + "@types/dompurify": "^3.0.5", + "@types/electron-localshortcut": "^3.1.0", + "@types/jest": "^27.4.1", + "@types/lodash": "^4.14.188", + "@types/md5": "^2.3.2", + "@types/node": "^22.14.1", + "@types/react": "^19.1.1", + "@types/react-dom": "^19.1.2", + "@types/react-test-renderer": "^17.0.1", + "@types/react-virtualized-auto-sizer": "^1.0.1", + "@types/react-window": "^1.8.5", + "@types/react-window-infinite-loader": "^1.0.6", + "@types/styled-components": "^5.1.26", + "@types/terser-webpack-plugin": "^5.0.4", + "@types/webpack-bundle-analyzer": "^4.4.1", + "@types/webpack-env": "^1.16.3", + "@typescript-eslint/eslint-plugin": "^5.47.0", + "@typescript-eslint/parser": "^5.47.0", + "@vitejs/plugin-react": "^4.3.4", + "browserslist-config-erb": "^0.0.3", + "chalk": "^4.1.2", + "concurrently": "^7.1.0", + "core-js": "^3.21.1", + "cross-env": "^7.0.3", + "css-loader": "^6.7.1", + "css-minimizer-webpack-plugin": "^3.4.1", + "detect-port": "^1.3.0", + "electron": "^35.1.5", + "electron-builder": "^25.1.8", + "electron-devtools-installer": "^3.2.0", + "electron-notarize": "^1.2.1", + "electron-vite": "^3.1.0", + "electronmon": "^2.0.2", + "eslint": "^9.24.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-erb": "^4.0.3", + "eslint-import-resolver-typescript": "^2.7.1", + "eslint-import-resolver-webpack": "^0.13.2", + "eslint-plugin-compat": "^4.2.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jest": "^26.1.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-perfectionist": "^4.13.0", + "eslint-plugin-prettier": "^5.4.0", + "eslint-plugin-promise": "^6.0.0", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.19", + "eslint-plugin-sort-keys-fix": "^1.1.2", + "eslint-plugin-typescript-sort-keys": "^2.1.0", + "file-loader": "^6.2.0", + "html-webpack-plugin": "^5.5.0", + "husky": "^7.0.4", + "i18next-parser": "^9.0.2", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.5.1", + "lint-staged": "^12.3.7", + "mini-css-extract-plugin": "^2.6.0", + "postcss-scss": "^4.0.4", + "postcss-styled-syntax": "^0.5.0", + "postcss-syntax": "^0.36.2", + "prettier": "^3.5.3", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-refresh": "^0.12.0", + "react-refresh-typescript": "^2.0.4", + "react-test-renderer": "^18.0.0", + "rimraf": "^3.0.2", + "sass": "^1.49.11", + "sass-embedded": "^1.89.0", + "sass-loader": "^12.6.0", + "style-loader": "^3.3.1", + "stylelint": "^15.10.3", + "stylelint-config-css-modules": "^4.3.0", + "stylelint-config-recess-order": "^4.3.0", + "stylelint-config-standard": "^34.0.0", + "stylelint-config-standard-scss": "^4.0.0", + "stylelint-config-styled-components": "^0.1.1", + "terser-webpack-plugin": "^5.3.1", + "ts-jest": "^27.1.4", + "ts-loader": "^9.2.8", + "ts-node": "^10.9.2", + "tsconfig-paths-webpack-plugin": "^4.0.0", + "tsx": "^4.16.2", + "typescript": "^5.8.3", + "typescript-plugin-styled-components": "^3.0.0", + "url-loader": "^4.1.1", + "vite": "^6.2.6", + "webpack": "^5.94.0", + "webpack-bundle-analyzer": "^4.5.0", + "webpack-cli": "^4.9.2", + "webpack-dev-server": "^4.8.0", + "webpack-merge": "^5.8.0" } } diff --git a/release/app/package-lock.json b/release/app/package-lock.json deleted file mode 100644 index 585958ec..00000000 --- a/release/app/package-lock.json +++ /dev/null @@ -1,2352 +0,0 @@ -{ - "name": "feishin", - "version": "0.12.8", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "feishin", - "version": "0.12.8", - "hasInstallScript": true, - "license": "GPL-3.0", - "dependencies": { - "cheerio": "^1.0.0-rc.12", - "mpris-service": "^2.1.2", - "ws": "^8.18.0" - }, - "devDependencies": { - "electron": "36.1.0" - } - }, - "node_modules/@electron/get": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.2.tgz", - "integrity": "sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^11.8.5", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "global-agent": "^3.0.0" - } - }, - "node_modules/@nornagon/put": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@nornagon/put/-/put-0.0.8.tgz", - "integrity": "sha512-ugvXJjwF5ldtUpa7D95kruNJ41yFQDEKyF5CW4TgKJnh+W/zmlBzXXeKTyqIgwMFrkePN2JqOBqcF0M0oOunow==", - "engines": { - "node": ">=0.3.0" - } - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "22.15.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.12.tgz", - "integrity": "sha512-K0fpC/ZVeb8G9rm7bH7vI0KAec4XHEhBam616nVJCV51bKzJ6oA3luG4WdKoaztxe70QaNjS/xBmcDLmr4PiGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/abstract-socket": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/abstract-socket/-/abstract-socket-2.1.1.tgz", - "integrity": "sha512-YZJizsvS1aBua5Gd01woe4zuyYBGgSMeqDOB6/ChwdTI904KP6QGtJswXl4hcqWxbz86hQBe++HWV0hF1aGUtA==", - "hasInstallScript": true, - "optional": true, - "os": [ - "linux" - ], - "dependencies": { - "bindings": "^1.2.1", - "nan": "^2.12.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "dev": true, - "optional": true - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/dbus-next": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/dbus-next/-/dbus-next-0.9.2.tgz", - "integrity": "sha512-tzQq/+wrTZ2yU+U5PoeXc97KABhX2v55C/T0finH3tSKYuI8H/SqppIFymBBrUHcK13LvEGY3vdj3ikPPenL5g==", - "dependencies": { - "@nornagon/put": "0.0.8", - "event-stream": "3.3.4", - "hexy": "^0.2.10", - "jsbi": "^2.0.5", - "long": "^4.0.0", - "safe-buffer": "^5.1.1", - "xml2js": "^0.4.17" - }, - "optionalDependencies": { - "abstract-socket": "^2.0.0" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dependencies": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "optional": true - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, - "node_modules/electron": { - "version": "36.1.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-36.1.0.tgz", - "integrity": "sha512-gnp3BnbKdGsVc7cm1qlEaZc8pJsR08mIs8H/yTo8gHEtFkGGJbDTVZOYNAfbQlL0aXh+ozv+CnyiNeDNkT1Upg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@electron/get": "^2.0.0", - "@types/node": "^22.7.7", - "extract-zip": "^2.0.1" - }, - "bin": { - "electron": "cli.js" - }, - "engines": { - "node": ">= 12.20.55" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "optional": true - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", - "dependencies": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/global-agent/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "optional": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "optional": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hexy": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.2.11.tgz", - "integrity": "sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==", - "bin": { - "hexy": "bin/hexy_cmd.js" - } - }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/jsbi": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-2.0.5.tgz", - "integrity": "sha512-TzO/62Hxeb26QMb4IGlI/5X+QLr9Uqp1FPkwp2+KOICW+Q+vSuFj61c8pkT6wAns4WcK56X7CmSHhJeDGWOqxQ==" - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "optional": true - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/keyv": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==" - }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "optional": true, - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mpris-service": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mpris-service/-/mpris-service-2.1.2.tgz", - "integrity": "sha512-AC6WepCnFWwOME9OWplHZ8ps/BB+g9QrEpUKCv7wX82fDPzR3nPrypOFmL/Fm0JloEAu6QTWSfDLLc6mM/jinw==", - "dependencies": { - "dbus-next": "^0.9.2", - "deep-equal": "^1.0.1", - "source-map-support": "^0.5.11" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "optional": true - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "optional": true - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "optional": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", - "dev": true, - "optional": true - }, - "node_modules/stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", - "dependencies": { - "duplexer": "~0.1.1" - } - }, - "node_modules/sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "dependencies": { - "debug": "^4.1.0" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "license": "MIT", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "optional": true - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - }, - "dependencies": { - "@electron/get": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.2.tgz", - "integrity": "sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "global-agent": "^3.0.0", - "got": "^11.8.5", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - } - }, - "@nornagon/put": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@nornagon/put/-/put-0.0.8.tgz", - "integrity": "sha512-ugvXJjwF5ldtUpa7D95kruNJ41yFQDEKyF5CW4TgKJnh+W/zmlBzXXeKTyqIgwMFrkePN2JqOBqcF0M0oOunow==" - }, - "@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "requires": { - "defer-to-connect": "^2.0.0" - } - }, - "@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "requires": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true - }, - "@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/node": { - "version": "22.15.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.12.tgz", - "integrity": "sha512-K0fpC/ZVeb8G9rm7bH7vI0KAec4XHEhBam616nVJCV51bKzJ6oA3luG4WdKoaztxe70QaNjS/xBmcDLmr4PiGw==", - "dev": true, - "requires": { - "undici-types": "~6.21.0" - } - }, - "@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, - "optional": true, - "requires": { - "@types/node": "*" - } - }, - "abstract-socket": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/abstract-socket/-/abstract-socket-2.1.1.tgz", - "integrity": "sha512-YZJizsvS1aBua5Gd01woe4zuyYBGgSMeqDOB6/ChwdTI904KP6QGtJswXl4hcqWxbz86hQBe++HWV0hF1aGUtA==", - "optional": true, - "requires": { - "bindings": "^1.2.1", - "nan": "^2.12.1" - } - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "dev": true, - "optional": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true - }, - "cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "requires": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - } - }, - "cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "requires": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - } - }, - "clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" - }, - "dbus-next": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/dbus-next/-/dbus-next-0.9.2.tgz", - "integrity": "sha512-tzQq/+wrTZ2yU+U5PoeXc97KABhX2v55C/T0finH3tSKYuI8H/SqppIFymBBrUHcK13LvEGY3vdj3ikPPenL5g==", - "requires": { - "@nornagon/put": "0.0.8", - "abstract-socket": "^2.0.0", - "event-stream": "3.3.4", - "hexy": "^0.2.10", - "jsbi": "^2.0.5", - "long": "^4.0.0", - "safe-buffer": "^5.1.1", - "xml2js": "0.5.0" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "requires": { - "mimic-response": "^3.1.0" - }, - "dependencies": { - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true - } - } - }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true - }, - "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "optional": true - }, - "dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "requires": { - "domelementtype": "^2.3.0" - } - }, - "domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "requires": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - } - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, - "electron": { - "version": "36.1.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-36.1.0.tgz", - "integrity": "sha512-gnp3BnbKdGsVc7cm1qlEaZc8pJsR08mIs8H/yTo8gHEtFkGGJbDTVZOYNAfbQlL0aXh+ozv+CnyiNeDNkT1Upg==", - "dev": true, - "requires": { - "@electron/get": "^2.0.0", - "@types/node": "^22.7.7", - "extract-zip": "^2.0.1" - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true - }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "optional": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "optional": true - }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" - }, - "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, - "optional": true, - "requires": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "dependencies": { - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "optional": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "optional": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "requires": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "hexy": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.2.11.tgz", - "integrity": "sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==" - }, - "htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "requires": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - } - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "jsbi": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-2.0.5.tgz", - "integrity": "sha512-TzO/62Hxeb26QMb4IGlI/5X+QLr9Uqp1FPkwp2+KOICW+Q+vSuFj61c8pkT6wAns4WcK56X7CmSHhJeDGWOqxQ==" - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "optional": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "keyv": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "optional": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==" - }, - "matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "optional": true, - "requires": { - "escape-string-regexp": "^4.0.0" - } - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true - }, - "mpris-service": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mpris-service/-/mpris-service-2.1.2.tgz", - "integrity": "sha512-AC6WepCnFWwOME9OWplHZ8ps/BB+g9QrEpUKCv7wX82fDPzR3nPrypOFmL/Fm0JloEAu6QTWSfDLLc6mM/jinw==", - "requires": { - "dbus-next": "^0.9.2", - "deep-equal": "^1.0.1", - "source-map-support": "^0.5.11" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "optional": true - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "requires": { - "boolbase": "^1.0.0" - } - }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "requires": { - "entities": "^4.4.0" - } - }, - "parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "requires": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - } - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "requires": { - "through": "~2.3" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true - }, - "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - } - }, - "resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "requires": { - "lowercase-keys": "^2.0.0" - } - }, - "roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "optional": true, - "requires": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "optional": true - }, - "serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "optional": true, - "requires": { - "type-fest": "^0.13.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", - "requires": { - "through": "2" - } - }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", - "dev": true, - "optional": true - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", - "requires": { - "duplexer": "~0.1.1" - } - }, - "sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "requires": { - "debug": "^4.1.0" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "optional": true - }, - "undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==" - }, - "xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "optional": true - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - } -} diff --git a/release/app/package.json b/release/app/package.json deleted file mode 100644 index 5891dfa0..00000000 --- a/release/app/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "feishin", - "version": "0.13.0", - "description": "", - "main": "./dist/main/main.js", - "author": { - "name": "jeffvli", - "url": "https://github.com/jeffvli/" - }, - "scripts": { - "electron-rebuild": "node -r ts-node/register ../../.erb/scripts/electron-rebuild.js", - "link-modules": "node -r ts-node/register ../../.erb/scripts/link-modules.ts", - "postinstall": "npm run electron-rebuild && npm run link-modules" - }, - "dependencies": { - "cheerio": "^1.0.0-rc.12", - "mpris-service": "^2.1.2", - "ws": "^8.18.0" - }, - "devDependencies": { - "electron": "36.1.0" - }, - "resolutions": { - "xml2js": "0.5.0" - }, - "overrides": { - "xml2js": "0.5.0" - }, - "license": "GPL-3.0" -} diff --git a/resources/icon.png b/resources/icon.png new file mode 100644 index 00000000..f364f2c1 Binary files /dev/null and b/resources/icon.png differ diff --git a/src/__tests__/App.test.tsx b/src/__tests__/App.test.tsx deleted file mode 100644 index b2f4b7d1..00000000 --- a/src/__tests__/App.test.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import '@testing-library/jest-dom'; -import { render } from '@testing-library/react'; -import { App } from '../renderer/app'; - -describe('App', () => { - it('should render', () => { - expect(render()).toBeTruthy(); - }); -}); diff --git a/src/i18n/i18n.ts b/src/i18n/i18n.ts index 90fd3013..0656d426 100644 --- a/src/i18n/i18n.ts +++ b/src/i18n/i18n.ts @@ -1,52 +1,53 @@ -import { PostProcessorModule, TOptions, StringMap } from 'i18next'; +import { PostProcessorModule, StringMap, TOptions } from 'i18next'; import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; + +import cs from './locales/cs.json'; +import de from './locales/de.json'; import en from './locales/en.json'; import es from './locales/es.json'; +import fa from './locales/fa.json'; +import fi from './locales/fi.json'; import fr from './locales/fr.json'; -import ja from './locales/ja.json'; -import pl from './locales/pl.json'; -import zhHans from './locales/zh-Hans.json'; -import de from './locales/de.json'; +import hu from './locales/hu.json'; +import id from './locales/id.json'; import it from './locales/it.json'; -import ru from './locales/ru.json'; -import ptBr from './locales/pt-BR.json'; -import sr from './locales/sr.json'; -import sv from './locales/sv.json'; -import cs from './locales/cs.json'; +import ja from './locales/ja.json'; +import ko from './locales/ko.json'; import nbNO from './locales/nb-NO.json'; import nl from './locales/nl.json'; -import zhHant from './locales/zh-Hant.json'; -import fa from './locales/fa.json'; -import ko from './locales/ko.json'; +import pl from './locales/pl.json'; +import ptBr from './locales/pt-BR.json'; +import ru from './locales/ru.json'; +import sr from './locales/sr.json'; +import sv from './locales/sv.json'; import ta from './locales/ta.json'; -import id from './locales/id.json'; -import fi from './locales/fi.json'; -import hu from './locales/hu.json'; +import zhHans from './locales/zh-Hans.json'; +import zhHant from './locales/zh-Hant.json'; const resources = { + cs: { translation: cs }, + de: { translation: de }, en: { translation: en }, es: { translation: es }, - de: { translation: de }, - it: { translation: it }, - ru: { translation: ru }, - 'pt-BR': { translation: ptBr }, fa: { translation: fa }, + fi: { translation: fi }, fr: { translation: fr }, + hu: { translation: hu }, + id: { translation: id }, + it: { translation: it }, ja: { translation: ja }, ko: { translation: ko }, + 'nb-NO': { translation: nbNO }, + nl: { translation: nl }, pl: { translation: pl }, - 'zh-Hans': { translation: zhHans }, - 'zh-Hant': { translation: zhHant }, + 'pt-BR': { translation: ptBr }, + ru: { translation: ru }, sr: { translation: sr }, sv: { translation: sv }, - cs: { translation: cs }, - nl: { translation: nl }, - 'nb-NO': { translation: nbNO }, ta: { translation: ta }, - id: { translation: id }, - fi: { translation: fi }, - hu: { translation: hu }, + 'zh-Hans': { translation: zhHans }, + 'zh-Hant': { translation: zhHant }, }; export const languages = [ @@ -141,35 +142,34 @@ export const languages = [ ]; const lowerCasePostProcessor: PostProcessorModule = { - type: 'postProcessor', name: 'lowerCase', process: (value: string) => { return value.toLocaleLowerCase(); }, + type: 'postProcessor', }; const upperCasePostProcessor: PostProcessorModule = { - type: 'postProcessor', name: 'upperCase', process: (value: string) => { return value.toLocaleUpperCase(); }, + type: 'postProcessor', }; const titleCasePostProcessor: PostProcessorModule = { - type: 'postProcessor', name: 'titleCase', process: (value: string) => { return value.replace(/\S\S*/g, (txt) => { return txt.charAt(0).toLocaleUpperCase() + txt.slice(1).toLowerCase(); }); }, + type: 'postProcessor', }; const ignoreSentenceCaseLanguages = ['de']; const sentenceCasePostProcessor: PostProcessorModule = { - type: 'postProcessor', name: 'sentenceCase', process: (value: string, _key: string, _options: TOptions, translator: any) => { const sentences = value.split('. '); @@ -185,6 +185,7 @@ const sentenceCasePostProcessor: PostProcessorModule = { }) .join('. '); }, + type: 'postProcessor', }; i18n.use(lowerCasePostProcessor) .use(upperCasePostProcessor) diff --git a/src/main/features/core/lyrics/genius.ts b/src/main/features/core/lyrics/genius.ts index f79489f5..e6be1964 100644 --- a/src/main/features/core/lyrics/genius.ts +++ b/src/main/features/core/lyrics/genius.ts @@ -1,12 +1,13 @@ import axios, { AxiosResponse } from 'axios'; import { load } from 'cheerio'; -import { orderSearchResults } from './shared'; + import { - LyricSource, InternetProviderLyricResponse, InternetProviderLyricSearchResponse, LyricSearchQuery, -} from '../../../../renderer/api/types'; + LyricSource, +} from '.'; +import { orderSearchResults } from './shared'; const SEARCH_URL = 'https://genius.com/api/search/song'; @@ -17,20 +18,6 @@ export interface GeniusResponse { response: Response; } -export interface Meta { - status: number; -} - -export interface Response { - next_page: number; - sections: Section[]; -} - -export interface Section { - hits: Hit[]; - type: string; -} - export interface Hit { highlights: any[]; index: string; @@ -38,6 +25,35 @@ export interface Hit { type: string; } +export interface Meta { + status: number; +} + +export interface PrimaryArtist { + _type: string; + api_path: string; + header_image_url: string; + id: number; + image_url: string; + index_character: string; + is_meme_verified: boolean; + is_verified: boolean; + name: string; + slug: string; + url: string; +} + +export interface ReleaseDateComponents { + day: number; + month: number; + year: number; +} + +export interface Response { + next_page: number; + sections: Section[]; +} + export interface Result { _type: string; annotation_count: number; @@ -69,24 +85,9 @@ export interface Result { url: string; } -export interface PrimaryArtist { - _type: string; - api_path: string; - header_image_url: string; - id: number; - image_url: string; - index_character: string; - is_meme_verified: boolean; - is_verified: boolean; - name: string; - slug: string; - url: string; -} - -export interface ReleaseDateComponents { - day: number; - month: number; - year: number; +export interface Section { + hits: Hit[]; + type: string; } export interface Stats { @@ -94,6 +95,27 @@ export interface Stats { unreviewed_annotations: number; } +export async function getLyricsBySongId(url: string): Promise { + let result: AxiosResponse; + try { + result = await axios.get(url, { responseType: 'text' }); + } catch (e) { + console.error('Genius lyrics request got an error!', e); + return null; + } + + const $ = load(result.data.split('
').join('\n')); + const lyricsDiv = $('div.lyrics'); + + if (lyricsDiv.length > 0) return lyricsDiv.text().trim(); + + const lyricSections = $('div[class^=Lyrics__Container]') + .map((_, e) => $(e).text()) + .toArray() + .join('\n'); + return lyricSections; +} + export async function getSearchResults( params: LyricSearchQuery, ): Promise { @@ -133,9 +155,33 @@ export async function getSearchResults( return orderSearchResults({ params, results: songResults }); } +export async function query( + params: LyricSearchQuery, +): Promise { + const response = await getSongId(params); + if (!response) { + console.error('Could not find the song on Genius!'); + return null; + } + + const lyrics = await getLyricsBySongId(response.id); + if (!lyrics) { + console.error('Could not get lyrics on Genius!'); + return null; + } + + return { + artist: response.artist, + id: response.id, + lyrics, + name: response.name, + source: LyricSource.GENIUS, + }; +} + async function getSongId( params: LyricSearchQuery, -): Promise | null> { +): Promise> { let result: AxiosResponse; try { result = await axios.get(SEARCH_URL, { @@ -162,48 +208,3 @@ async function getSongId( source: LyricSource.GENIUS, }; } - -export async function getLyricsBySongId(url: string): Promise { - let result: AxiosResponse; - try { - result = await axios.get(url, { responseType: 'text' }); - } catch (e) { - console.error('Genius lyrics request got an error!', e); - return null; - } - - const $ = load(result.data.split('
').join('\n')); - const lyricsDiv = $('div.lyrics'); - - if (lyricsDiv.length > 0) return lyricsDiv.text().trim(); - - const lyricSections = $('div[class^=Lyrics__Container]') - .map((_, e) => $(e).text()) - .toArray() - .join('\n'); - return lyricSections; -} - -export async function query( - params: LyricSearchQuery, -): Promise { - const response = await getSongId(params); - if (!response) { - console.error('Could not find the song on Genius!'); - return null; - } - - const lyrics = await getLyricsBySongId(response.id); - if (!lyrics) { - console.error('Could not get lyrics on Genius!'); - return null; - } - - return { - artist: response.artist, - id: response.id, - lyrics, - name: response.name, - source: LyricSource.GENIUS, - }; -} diff --git a/src/main/features/core/lyrics/index.ts b/src/main/features/core/lyrics/index.ts index c3fc781e..a4b72c6d 100644 --- a/src/main/features/core/lyrics/index.ts +++ b/src/main/features/core/lyrics/index.ts @@ -1,36 +1,76 @@ import { ipcMain } from 'electron'; + +import { store } from '../settings/index'; import { + getLyricsBySongId as getGenius, query as queryGenius, getSearchResults as searchGenius, - getLyricsBySongId as getGenius, } from './genius'; import { + getLyricsBySongId as getLrcLib, query as queryLrclib, getSearchResults as searchLrcLib, - getLyricsBySongId as getLrcLib, } from './lrclib'; import { + getLyricsBySongId as getNetease, query as queryNetease, getSearchResults as searchNetease, - getLyricsBySongId as getNetease, } from './netease'; -import { - InternetProviderLyricResponse, - InternetProviderLyricSearchResponse, - LyricSearchQuery, - QueueSong, - LyricGetQuery, - LyricSource, -} from '../../../../renderer/api/types'; -import { store } from '../settings/index'; -type SongFetcher = (params: LyricSearchQuery) => Promise; +export enum LyricSource { + GENIUS = 'Genius', + LRCLIB = 'lrclib.net', + NETEASE = 'NetEase', +} + +export type FullLyricsMetadata = Omit & { + lyrics: LyricsResponse; + remote: boolean; + source: string; +}; + +export type InternetProviderLyricResponse = { + artist: string; + id: string; + lyrics: string; + name: string; + source: LyricSource; +}; + +export type InternetProviderLyricSearchResponse = { + artist: string; + id: string; + name: string; + score?: number; + source: LyricSource; +}; + +export type LyricGetQuery = { + remoteSongId: string; + remoteSource: LyricSource; + song: Song; +}; + +export type LyricOverride = Omit; + +export type LyricSearchQuery = { + album?: string; + artist?: string; + duration?: number; + name?: string; +}; + +export type LyricsResponse = string | SynchronizedLyricsArray; + +export type SynchronizedLyricsArray = Array<[number, string]>; + +type CachedLyrics = Record; +type GetFetcher = (id: string) => Promise; type SearchFetcher = ( params: LyricSearchQuery, ) => Promise; -type GetFetcher = (id: string) => Promise; -type CachedLyrics = Record; +type SongFetcher = (params: LyricSearchQuery) => Promise; const FETCHERS: Record = { [LyricSource.GENIUS]: queryGenius, @@ -54,7 +94,7 @@ const MAX_CACHED_ITEMS = 10; const lyricCache = new Map(); -const getRemoteLyrics = async (song: QueueSong) => { +const getRemoteLyrics = async (song: any) => { const sources = store.get('lyrics', []) as LyricSource[]; const cached = lyricCache.get(song.id); @@ -122,7 +162,7 @@ const searchRemoteLyrics = async (params: LyricSearchQuery) => { return results; }; -const getRemoteLyricsById = async (params: LyricGetQuery): Promise => { +const getRemoteLyricsById = async (params: LyricGetQuery): Promise => { const { remoteSongId, remoteSource } = params; const response = await GET_FETCHERS[remoteSource](remoteSongId); @@ -133,7 +173,7 @@ const getRemoteLyricsById = async (params: LyricGetQuery): Promise { +ipcMain.handle('lyric-by-song', async (_event, song: any) => { const lyric = await getRemoteLyrics(song); return lyric; }); diff --git a/src/main/features/core/lyrics/lrclib.ts b/src/main/features/core/lyrics/lrclib.ts index 3074b73d..d2ac0512 100644 --- a/src/main/features/core/lyrics/lrclib.ts +++ b/src/main/features/core/lyrics/lrclib.ts @@ -1,12 +1,13 @@ // Credits to https://github.com/tranxuanthang/lrcget for API implementation import axios, { AxiosResponse } from 'axios'; -import { orderSearchResults } from './shared'; + import { InternetProviderLyricResponse, InternetProviderLyricSearchResponse, LyricSearchQuery, LyricSource, -} from '../../../../renderer/api/types'; +} from '.'; +import { orderSearchResults } from './shared'; const FETCH_URL = 'https://lrclib.net/api/get'; const SEEARCH_URL = 'https://lrclib.net/api/search'; @@ -29,10 +30,23 @@ export interface LrcLibTrackResponse { isrc: string; lang: string; name: string; - plainLyrics: string | null; + plainLyrics: null | string; releaseDate: string; spotifyId: string; - syncedLyrics: string | null; + syncedLyrics: null | string; +} + +export async function getLyricsBySongId(songId: string): Promise { + let result: AxiosResponse; + + try { + result = await axios.get(`${FETCH_URL}/${songId}`); + } catch (e) { + console.error('LrcLib lyrics request got an error!', e); + return null; + } + + return result.data.syncedLyrics || result.data.plainLyrics || null; } export async function getSearchResults( @@ -69,19 +83,6 @@ export async function getSearchResults( return orderSearchResults({ params, results: songResults }); } -export async function getLyricsBySongId(songId: string): Promise { - let result: AxiosResponse; - - try { - result = await axios.get(`${FETCH_URL}/${songId}`); - } catch (e) { - console.error('LrcLib lyrics request got an error!', e); - return null; - } - - return result.data.syncedLyrics || result.data.plainLyrics || null; -} - export async function query( params: LyricSearchQuery, ): Promise { diff --git a/src/main/features/core/lyrics/netease.ts b/src/main/features/core/lyrics/netease.ts index b97ca3f8..d59f9faf 100644 --- a/src/main/features/core/lyrics/netease.ts +++ b/src/main/features/core/lyrics/netease.ts @@ -1,46 +1,18 @@ import axios, { AxiosResponse } from 'axios'; -import { LyricSource } from '../../../../renderer/api/types'; -import { orderSearchResults } from './shared'; -import type { + +import { InternetProviderLyricResponse, InternetProviderLyricSearchResponse, LyricSearchQuery, -} from '/@/renderer/api/types'; + LyricSource, +} from '.'; +import { orderSearchResults } from './shared'; const SEARCH_URL = 'https://music.163.com/api/search/get'; const LYRICS_URL = 'https://music.163.com/api/song/lyric'; // Adapted from https://github.com/NyaomiDEV/Sunamu/blob/master/src/main/lyricproviders/netease.ts -export interface NetEaseResponse { - code: number; - result: Result; -} - -export interface Result { - hasMore: boolean; - songCount: number; - songs: Song[]; -} - -export interface Song { - album: Album; - alias: string[]; - artists: Artist[]; - copyrightId: number; - duration: number; - fee: number; - ftype: number; - id: number; - mark: number; - mvid: number; - name: string; - rUrl: null; - rtype: number; - status: number; - transNames?: string[]; -} - export interface Album { artist: Artist; copyrightId: number; @@ -67,6 +39,53 @@ export interface Artist { trans: null; } +export interface NetEaseResponse { + code: number; + result: Result; +} + +export interface Result { + hasMore: boolean; + songCount: number; + songs: Song[]; +} + +export interface Song { + album: Album; + alias: string[]; + artists: Artist[]; + copyrightId: number; + duration: number; + fee: number; + ftype: number; + id: number; + mark: number; + mvid: number; + name: string; + rtype: number; + rUrl: null; + status: number; + transNames?: string[]; +} + +export async function getLyricsBySongId(songId: string): Promise { + let result: AxiosResponse; + try { + result = await axios.get(LYRICS_URL, { + params: { + id: songId, + kv: '-1', + lv: '-1', + }, + }); + } catch (e) { + console.error('NetEase lyrics request got an error!', e); + return null; + } + + return result.data.klyric?.lyric || result.data.lrc?.lyric; +} + export async function getSearchResults( params: LyricSearchQuery, ): Promise { @@ -110,38 +129,6 @@ export async function getSearchResults( return orderSearchResults({ params, results: songResults }); } -async function getMatchedLyrics( - params: LyricSearchQuery, -): Promise | null> { - const results = await getSearchResults(params); - - const firstMatch = results?.[0]; - - if (!firstMatch || (firstMatch?.score && firstMatch.score > 0.5)) { - return null; - } - - return firstMatch; -} - -export async function getLyricsBySongId(songId: string): Promise { - let result: AxiosResponse; - try { - result = await axios.get(LYRICS_URL, { - params: { - id: songId, - kv: '-1', - lv: '-1', - }, - }); - } catch (e) { - console.error('NetEase lyrics request got an error!', e); - return null; - } - - return result.data.klyric?.lyric || result.data.lrc?.lyric; -} - export async function query( params: LyricSearchQuery, ): Promise { @@ -165,3 +152,17 @@ export async function query( source: LyricSource.NETEASE, }; } + +async function getMatchedLyrics( + params: LyricSearchQuery, +): Promise> { + const results = await getSearchResults(params); + + const firstMatch = results?.[0]; + + if (!firstMatch || (firstMatch?.score && firstMatch.score > 0.5)) { + return null; + } + + return firstMatch; +} diff --git a/src/main/features/core/lyrics/shared.ts b/src/main/features/core/lyrics/shared.ts index bb926f28..44dc4853 100644 --- a/src/main/features/core/lyrics/shared.ts +++ b/src/main/features/core/lyrics/shared.ts @@ -1,4 +1,5 @@ import Fuse from 'fuse.js'; + import { InternetProviderLyricSearchResponse, LyricSearchQuery, diff --git a/src/main/features/core/player/index.ts b/src/main/features/core/player/index.ts index 67152b65..b0e88582 100644 --- a/src/main/features/core/player/index.ts +++ b/src/main/features/core/player/index.ts @@ -1,10 +1,11 @@ import console from 'console'; -import { rm } from 'fs/promises'; -import { pid } from 'node:process'; import { app, ipcMain } from 'electron'; +import { rm } from 'fs/promises'; import uniq from 'lodash/uniq'; import MpvAPI from 'node-mpv'; -import { getMainWindow, sendToastToRenderer } from '../../../main'; +import { pid } from 'node:process'; + +import { getMainWindow, sendToastToRenderer } from '../../../index'; import { createLog, isWindows } from '../../../utils'; import { store } from '../settings'; @@ -86,7 +87,7 @@ const createMpv = async (data: { extraParameters?: string[]; properties?: Record; }): Promise => { - const { extraParameters, properties, binaryPath } = data; + const { binaryPath, extraParameters, properties } = data; const params = uniq([...DEFAULT_MPV_PARAMETERS(extraParameters), ...(extraParameters || [])]); @@ -174,7 +175,7 @@ ipcMain.on('player-set-properties', async (_event, data: Record) => } else { getMpvInstance()?.setMultipleProperties(data); } - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to set properties: ${JSON.stringify(data)}` }, err); } }); @@ -199,7 +200,7 @@ ipcMain.handle( mpvInstance = await createMpv(data); mpvLog({ action: 'Restarted mpv', toast: 'success' }); setAudioPlayerFallback(false); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: 'Failed to restart mpv, falling back to web player' }, err); setAudioPlayerFallback(true); } @@ -215,7 +216,7 @@ ipcMain.handle( }); mpvInstance = await createMpv(data); setAudioPlayerFallback(false); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: 'Failed to initialize mpv, falling back to web player' }, err); setAudioPlayerFallback(true); } @@ -226,7 +227,7 @@ ipcMain.on('player-quit', async () => { try { await getMpvInstance()?.stop(); await quit(); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: 'Failed to quit mpv' }, err); } finally { mpvInstance = null; @@ -245,7 +246,7 @@ ipcMain.handle('player-clean-up', async () => { ipcMain.on('player-start', async () => { try { await getMpvInstance()?.play(); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: 'Failed to start mpv playback' }, err); } }); @@ -254,7 +255,7 @@ ipcMain.on('player-start', async () => { ipcMain.on('player-play', async () => { try { await getMpvInstance()?.play(); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: 'Failed to start mpv playback' }, err); } }); @@ -263,7 +264,7 @@ ipcMain.on('player-play', async () => { ipcMain.on('player-pause', async () => { try { await getMpvInstance()?.pause(); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: 'Failed to pause mpv playback' }, err); } }); @@ -272,7 +273,7 @@ ipcMain.on('player-pause', async () => { ipcMain.on('player-stop', async () => { try { await getMpvInstance()?.stop(); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: 'Failed to stop mpv playback' }, err); } }); @@ -281,7 +282,7 @@ ipcMain.on('player-stop', async () => { ipcMain.on('player-next', async () => { try { await getMpvInstance()?.next(); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: 'Failed to go to next track' }, err); } }); @@ -290,7 +291,7 @@ ipcMain.on('player-next', async () => { ipcMain.on('player-previous', async () => { try { await getMpvInstance()?.prev(); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: 'Failed to go to previous track' }, err); } }); @@ -299,7 +300,7 @@ ipcMain.on('player-previous', async () => { ipcMain.on('player-seek', async (_event, time: number) => { try { await getMpvInstance()?.seek(time); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to seek by ${time} seconds` }, err); } }); @@ -308,7 +309,7 @@ ipcMain.on('player-seek', async (_event, time: number) => { ipcMain.on('player-seek-to', async (_event, time: number) => { try { await getMpvInstance()?.goToPosition(time); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to seek to ${time} seconds` }, err); } }); @@ -320,7 +321,7 @@ ipcMain.on('player-set-queue', async (_event, current?: string, next?: string, p await getMpvInstance()?.clearPlaylist(); await getMpvInstance()?.pause(); return; - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to clear play queue` }, err); } } @@ -344,7 +345,7 @@ ipcMain.on('player-set-queue', async (_event, current?: string, next?: string, p // Only force play if pause is explicitly false await getMpvInstance()?.play(); } - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to set play queue` }, err); } }); @@ -365,7 +366,7 @@ ipcMain.on('player-set-queue-next', async (_event, url?: string) => { if (url) { await getMpvInstance()?.load(url, 'append'); } - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to set play queue` }, err); } }); @@ -385,7 +386,7 @@ ipcMain.on('player-auto-next', async (_event, url?: string) => { if (url) { await getMpvInstance()?.load(url, 'append'); } - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to load next song` }, err); } }); @@ -398,7 +399,7 @@ ipcMain.on('player-volume', async (_event, value: number) => { } await getMpvInstance()?.volume(value); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to set volume to ${value}` }, err); } }); @@ -407,7 +408,7 @@ ipcMain.on('player-volume', async (_event, value: number) => { ipcMain.on('player-mute', async (_event, mute: boolean) => { try { await getMpvInstance()?.mute(mute); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to set mute status` }, err); } }); @@ -415,7 +416,7 @@ ipcMain.on('player-mute', async (_event, mute: boolean) => { ipcMain.handle('player-get-time', async (): Promise => { try { return getMpvInstance()?.getTimePosition(); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to get current time` }, err); return 0; } @@ -442,7 +443,7 @@ app.on('before-quit', async (event) => { event.preventDefault(); await getMpvInstance()?.stop(); await quit(); - } catch (err: NodeMpvError | any) { + } catch (err: any | NodeMpvError) { mpvLog({ action: `Failed to cleanly before-quit` }, err); } finally { mpvState = MpvState.DONE; diff --git a/src/main/features/core/player/media-keys.ts b/src/main/features/core/player/media-keys.ts index b87f9ee1..e919fb29 100644 --- a/src/main/features/core/player/media-keys.ts +++ b/src/main/features/core/player/media-keys.ts @@ -1,5 +1,6 @@ /* eslint-disable promise/always-return */ import { BrowserWindow, globalShortcut, systemPreferences } from 'electron'; + import { isMacOS } from '../../../utils'; import { store } from '../settings'; diff --git a/src/main/features/core/remote/index.ts b/src/main/features/core/remote/index.ts index 0adcf835..9fd0a686 100644 --- a/src/main/features/core/remote/index.ts +++ b/src/main/features/core/remote/index.ts @@ -1,32 +1,22 @@ -import { Stats, promises } from 'fs'; -import { readFile } from 'fs/promises'; -import { IncomingMessage, Server, ServerResponse, createServer } from 'http'; -import { join } from 'path'; -import { deflate, gzip } from 'zlib'; import axios from 'axios'; import { app, ipcMain } from 'electron'; -import { Server as WsServer, WebSocketServer, WebSocket } from 'ws'; -import manifest from './manifest.json'; -import { ClientEvent, ServerEvent } from '../../../../remote/types'; -import { PlayerRepeat, PlayerStatus, SongState } from '../../../../renderer/types'; -import { getMainWindow } from '../../../main'; +import { promises, Stats } from 'fs'; +import { readFile } from 'fs/promises'; +import { createServer, IncomingMessage, Server, ServerResponse } from 'http'; +import { join } from 'path'; +import { WebSocket, WebSocketServer, Server as WsServer } from 'ws'; +import { deflate, gzip } from 'zlib'; + +import { getMainWindow } from '../../..'; import { isLinux } from '../../../utils'; -import type { QueueSong } from '/@/renderer/api/types'; +import manifest from './manifest.json'; let mprisPlayer: any | undefined; if (isLinux()) { - // eslint-disable-next-line global-require mprisPlayer = require('../../linux/mpris').mprisPlayer; } -interface RemoteConfig { - enabled: boolean; - password: string; - port: number; - username: string; -} - interface MimeType { css: string; html: string; @@ -34,6 +24,13 @@ interface MimeType { js: string; } +interface RemoteConfig { + enabled: boolean; + password: string; + port: number; + username: string; +} + declare class StatefulWebSocket extends WebSocket { alive: boolean; @@ -41,7 +38,7 @@ declare class StatefulWebSocket extends WebSocket { } let server: Server | undefined; -let wsServer: WsServer | undefined; +let wsServer: undefined | WsServer; const settings: RemoteConfig = { enabled: false, @@ -54,14 +51,6 @@ type SendData = ServerEvent & { client: StatefulWebSocket; }; -function send({ client, event, data }: SendData): void { - if (client.readyState === WebSocket.OPEN) { - if (client.alive && client.auth) { - client.send(JSON.stringify({ data, event })); - } - } -} - function broadcast(message: ServerEvent): void { if (wsServer) { for (const client of wsServer.clients) { @@ -70,6 +59,14 @@ function broadcast(message: ServerEvent): void { } } +function send({ client, data, event }: SendData): void { + if (client.readyState === WebSocket.OPEN) { + if (client.alive && client.auth) { + client.send(JSON.stringify({ data, event })); + } + } +} + const shutdownServer = () => { if (wsServer) { wsServer.clients.forEach((client) => client.close(4000)); @@ -121,21 +118,17 @@ const getEncoding = (encoding: string | string[]): Encoding => { const cache = new Map>(); -function setOk( - res: ServerResponse, - mtimeMs: number, - extension: keyof MimeType, - encoding: Encoding, - data?: Buffer, -) { - res.statusCode = data ? 200 : 304; +function authorize(req: IncomingMessage): boolean { + if (settings.username || settings.password) { + // https://stackoverflow.com/questions/23616371/basic-http-authentication-with-node-and-express-4 - res.setHeader('Content-Type', MIME_TYPES[extension]); - res.setHeader('ETag', `"${mtimeMs}"`); - res.setHeader('Cache-Control', 'public'); + const authorization = req.headers.authorization?.split(' ')[1] || ''; + const [login, password] = Buffer.from(authorization, 'base64').toString().split(':'); - if (encoding !== 'none') res.setHeader('Content-Encoding', encoding); - res.end(data); + return login === settings.username && password === settings.password; + } + + return true; } async function serveFile( @@ -252,17 +245,21 @@ async function serveFile( return Promise.resolve(); } -function authorize(req: IncomingMessage): boolean { - if (settings.username || settings.password) { - // https://stackoverflow.com/questions/23616371/basic-http-authentication-with-node-and-express-4 +function setOk( + res: ServerResponse, + mtimeMs: number, + extension: keyof MimeType, + encoding: Encoding, + data?: Buffer, +) { + res.statusCode = data ? 200 : 304; - const authorization = req.headers.authorization?.split(' ')[1] || ''; - const [login, password] = Buffer.from(authorization, 'base64').toString().split(':'); + res.setHeader('Content-Type', MIME_TYPES[extension]); + res.setHeader('ETag', `"${mtimeMs}"`); + res.setHeader('Cache-Control', 'public'); - return login === settings.username && password === settings.password; - } - - return true; + if (encoding !== 'none') res.setHeader('Content-Encoding', encoding); + res.end(data); } const enableServer = (config: RemoteConfig): Promise => { @@ -286,28 +283,28 @@ const enableServer = (config: RemoteConfig): Promise => { await serveFile(req, 'index', 'html', res); break; } + case '/credentials': { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.end(req.headers.authorization); + break; + } case '/favicon.ico': { await serveFile(req, 'favicon', 'ico', res); break; } - case '/remote.css': { - await serveFile(req, 'remote', 'css', res); - break; - } - case '/remote.js': { - await serveFile(req, 'remote', 'js', res); - break; - } case '/manifest.json': { res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(manifest)); break; } - case '/credentials': { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - res.end(req.headers.authorization); + case '/remote.css': { + await serveFile(req, 'remote', 'css', res); + break; + } + case '/remote.js': { + await serveFile(req, 'remote', 'js', res); break; } default: { @@ -371,6 +368,21 @@ const enableServer = (config: RemoteConfig): Promise => { } switch (event) { + case 'favorite': { + const { favorite, id } = json; + if (id && id === currentState.song?.id) { + getMainWindow()?.webContents.send('request-favorite', { + favorite, + id, + serverId: currentState.song.serverId, + }); + } + break; + } + case 'next': { + getMainWindow()?.webContents.send('renderer-player-next'); + break; + } case 'pause': { getMainWindow()?.webContents.send('renderer-player-pause'); break; @@ -379,10 +391,6 @@ const enableServer = (config: RemoteConfig): Promise => { getMainWindow()?.webContents.send('renderer-player-play'); break; } - case 'next': { - getMainWindow()?.webContents.send('renderer-player-next'); - break; - } case 'previous': { getMainWindow()?.webContents.send('renderer-player-previous'); break; @@ -421,6 +429,17 @@ const enableServer = (config: RemoteConfig): Promise => { break; } + case 'rating': { + const { id, rating } = json; + if (id && id === currentState.song?.id) { + getMainWindow()?.webContents.send('request-rating', { + id, + rating, + serverId: currentState.song.serverId, + }); + } + break; + } case 'repeat': { getMainWindow()?.webContents.send('renderer-player-toggle-repeat'); break; @@ -450,28 +469,6 @@ const enableServer = (config: RemoteConfig): Promise => { } break; } - case 'favorite': { - const { favorite, id } = json; - if (id && id === currentState.song?.id) { - getMainWindow()?.webContents.send('request-favorite', { - favorite, - id, - serverId: currentState.song.serverId, - }); - } - break; - } - case 'rating': { - const { rating, id } = json; - if (id && id === currentState.song?.id) { - getMainWindow()?.webContents.send('request-rating', { - id, - rating, - serverId: currentState.song.serverId, - }); - } - break; - } case 'position': { const { position } = json; if (mprisPlayer) { @@ -631,12 +628,7 @@ ipcMain.on('update-volume', (_event, volume: number) => { if (mprisPlayer) { mprisPlayer.on('loopStatus', (event: string) => { - const repeat = - event === 'Playlist' - ? PlayerRepeat.ALL - : event === 'Track' - ? PlayerRepeat.ONE - : PlayerRepeat.NONE; + const repeat = event === 'Playlist' ? 'all' : event === 'Track' ? 'one' : 'none'; currentState.repeat = repeat; broadcast({ data: repeat, event: 'repeat' }); diff --git a/src/main/features/core/settings/index.ts b/src/main/features/core/settings/index.ts index f829ea58..05cd0ad3 100644 --- a/src/main/features/core/settings/index.ts +++ b/src/main/features/core/settings/index.ts @@ -1,6 +1,7 @@ +import type { TitleTheme } from '/@/renderer/types'; + import { ipcMain, nativeTheme, safeStorage } from 'electron'; import Store from 'electron-store'; -import type { TitleTheme } from '/@/renderer/types'; export const store = new Store(); @@ -12,7 +13,7 @@ ipcMain.on('settings-set', (__event, data: { property: string; value: any }) => store.set(`${data.property}`, data.value); }); -ipcMain.handle('password-get', (_event, server: string): string | null => { +ipcMain.handle('password-get', (_event, server: string): null | string => { if (safeStorage.isEncryptionAvailable()) { const servers = store.get('server') as Record | undefined; diff --git a/src/main/features/index.ts b/src/main/features/index.ts index e64d7d9f..b80182ff 100644 --- a/src/main/features/index.ts +++ b/src/main/features/index.ts @@ -1,4 +1,3 @@ import './core'; -// eslint-disable-next-line import/no-dynamic-require -require(`./${process.platform}`); +// require(`./${process.platform}`) diff --git a/src/main/features/linux/mpris.ts b/src/main/features/linux/mpris.ts index 6d400f8e..f53eeb8d 100644 --- a/src/main/features/linux/mpris.ts +++ b/src/main/features/linux/mpris.ts @@ -1,7 +1,9 @@ import { ipcMain } from 'electron'; import Player from 'mpris-service'; + import { PlayerRepeat, PlayerStatus } from '../../../renderer/types'; import { getMainWindow } from '../../main'; + import { QueueSong } from '/@/renderer/api/types'; const mprisPlayer = Player({ @@ -124,8 +126,8 @@ ipcMain.on('update-playback', (_event, status: PlayerStatus) => { const REPEAT_TO_MPRIS: Record = { [PlayerRepeat.ALL]: 'Playlist', - [PlayerRepeat.ONE]: 'Track', [PlayerRepeat.NONE]: 'None', + [PlayerRepeat.ONE]: 'Track', }; ipcMain.on('update-repeat', (_event, arg: PlayerRepeat) => { diff --git a/src/main/features/win32/index.ts b/src/main/features/win32/index.ts index e69de29b..1b7c8727 100644 --- a/src/main/features/win32/index.ts +++ b/src/main/features/win32/index.ts @@ -0,0 +1,3 @@ +// Dummy file to satisfy the build system + +export {}; diff --git a/src/main/main.ts b/src/main/index.ts similarity index 91% rename from src/main/main.ts rename to src/main/index.ts index 802fc3b9..ed679488 100644 --- a/src/main/main.ts +++ b/src/main/index.ts @@ -1,51 +1,40 @@ -/* eslint global-require: off, no-console: off, promise/always-return: off */ - -/** - * This module executes inside of electron's main process. You can start - * electron renderer process from here and communicate with the other processes - * through IPC. - * - * When running `npm run build` or `npm run build:main`, this file is compiled to - * `./src/main.js` using webpack. This gives us some performance wins. - */ -import { access, constants, readFile, writeFile } from 'fs'; -import path, { join } from 'path'; -import { deflate, inflate } from 'zlib'; +import { electronApp, is, optimizer } from '@electron-toolkit/utils'; +import { constants } from 'buffer'; import { app, BrowserWindow, - shell, - ipcMain, + BrowserWindowConstructorOptions, globalShortcut, - Tray, + ipcMain, Menu, nativeImage, nativeTheme, - BrowserWindowConstructorOptions, - protocol, net, + protocol, Rectangle, screen, + shell, + Tray, } from 'electron'; import electronLocalShortcut from 'electron-localshortcut'; import log from 'electron-log/main'; import { autoUpdater } from 'electron-updater'; +import { access, readFile, writeFile } from 'fs'; +import path, { join } from 'path'; +import { deflate, inflate } from 'zlib'; + import { disableMediaKeys, enableMediaKeys } from './features/core/player/media-keys'; -import { store } from './features/core/settings/index'; +import { store } from './features/core/settings'; import MenuBuilder from './menu'; import { + autoUpdaterLogInterface, + createLog, hotkeyToElectronAccelerator, isLinux, isMacOS, isWindows, - resolveHtmlPath, - createLog, - autoUpdaterLogInterface, } from './utils'; import './features'; -import type { TitleTheme } from '/@/renderer/types'; - -declare module 'node-mpv'; export default class AppUpdater { constructor() { @@ -72,7 +61,7 @@ if (isLinux() && !process.argv.some((a) => a.startsWith('--password-store='))) { } let mainWindow: BrowserWindow | null = null; -let tray: Tray | null = null; +let tray: null | Tray = null; let exitFromTray = false; let forceQuit = false; @@ -117,7 +106,7 @@ export const sendToastToRenderer = ({ type, }: { message: string; - type: 'success' | 'error' | 'warning' | 'info'; + type: 'error' | 'info' | 'success' | 'warning'; }) => { getMainWindow()?.webContents.send('toast-from-main', { message, @@ -208,7 +197,7 @@ const createTray = () => { tray.setContextMenu(contextMenu); }; -const createWindow = async (first = true) => { +async function createWindow(first = true): Promise { if (isDevelopment) { await installExtensions().catch(console.log); } @@ -233,6 +222,7 @@ const createWindow = async (first = true) => { }, }; + // Create the browser window. mainWindow = new BrowserWindow({ autoHideMenuBar: true, frame: false, @@ -247,9 +237,8 @@ const createWindow = async (first = true) => { contextIsolation: true, devTools: true, nodeIntegration: true, - preload: app.isPackaged - ? path.join(__dirname, 'preload.js') - : path.join(__dirname, '../../.erb/dll/preload.js'), + preload: join(__dirname, '../preload/index.js'), + sandbox: false, webSecurity: !store.get('ignore_cors'), }, width: 1440, @@ -374,11 +363,11 @@ const createWindow = async (first = true) => { enableMediaKeys(mainWindow); } - mainWindow.loadURL(resolveHtmlPath('index.html')); - const startWindowMinimized = store.get('window_start_minimized', false) as boolean; mainWindow.on('ready-to-show', () => { + // mainWindow.show() + if (!mainWindow) { throw new Error('"mainWindow" is not defined'); } @@ -404,7 +393,7 @@ const createWindow = async (first = true) => { mainWindow = null; }); - let saved = false; + const saved = false; mainWindow.on('close', (event) => { store.set('bounds', mainWindow?.getNormalBounds()); @@ -484,13 +473,25 @@ const createWindow = async (first = true) => { }); if (store.get('disable_auto_updates') !== true) { - // eslint-disable-next-line new AppUpdater(); } const theme = store.get('theme') as TitleTheme | undefined; nativeTheme.themeSource = theme || 'dark'; -}; + + mainWindow.webContents.setWindowOpenHandler((details) => { + shell.openExternal(details.url); + return { action: 'deny' }; + }); + + // HMR for renderer base on electron-vite cli. + // Load the remote URL for development or the local html file for production. + if (is.dev && process.env['ELECTRON_RENDERER_URL']) { + mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']); + } else { + mainWindow.loadFile(join(__dirname, '../renderer/index.html')); + } +} app.commandLine.appendSwitch('disable-features', 'HardwareMediaKeyHandling,MediaSessionService'); @@ -519,6 +520,8 @@ enum BindingActions { } const HOTKEY_ACTIONS: Record void> = { + [BindingActions.GLOBAL_SEARCH]: () => {}, + [BindingActions.LOCAL_SEARCH]: () => {}, [BindingActions.MUTE]: () => getMainWindow()?.webContents.send('renderer-player-volume-mute'), [BindingActions.NEXT]: () => getMainWindow()?.webContents.send('renderer-player-next'), [BindingActions.PAUSE]: () => getMainWindow()?.webContents.send('renderer-player-pause'), @@ -533,16 +536,14 @@ const HOTKEY_ACTIONS: Record void> = { [BindingActions.SKIP_FORWARD]: () => getMainWindow()?.webContents.send('renderer-player-skip-forward'), [BindingActions.STOP]: () => getMainWindow()?.webContents.send('renderer-player-stop'), + [BindingActions.TOGGLE_FULLSCREEN_PLAYER]: () => {}, + [BindingActions.TOGGLE_QUEUE]: () => {}, [BindingActions.TOGGLE_REPEAT]: () => getMainWindow()?.webContents.send('renderer-player-toggle-repeat'), - [BindingActions.VOLUME_UP]: () => - getMainWindow()?.webContents.send('renderer-player-volume-up'), [BindingActions.VOLUME_DOWN]: () => getMainWindow()?.webContents.send('renderer-player-volume-down'), - [BindingActions.GLOBAL_SEARCH]: () => {}, - [BindingActions.LOCAL_SEARCH]: () => {}, - [BindingActions.TOGGLE_QUEUE]: () => {}, - [BindingActions.TOGGLE_FULLSCREEN_PLAYER]: () => {}, + [BindingActions.VOLUME_UP]: () => + getMainWindow()?.webContents.send('renderer-player-volume-up'), }; ipcMain.on( @@ -585,7 +586,7 @@ ipcMain.on( _event, data: { message: string; - type: 'debug' | 'verbose' | 'success' | 'error' | 'warning' | 'info'; + type: 'debug' | 'error' | 'info' | 'success' | 'verbose' | 'warning'; }, ) => { createLog(data); @@ -597,7 +598,6 @@ app.on('window-all-closed', () => { // Respect the OSX convention of having the application in memory even // after all windows have been closed if (isMacOS()) { - ipcMain.removeHandler('window-clear-cache'); mainWindow = null; } else { app.quit(); @@ -632,22 +632,22 @@ if (!singleInstance) { app.whenReady() .then(() => { - protocol.handle('feishin', async (request) => { - const filePath = `file://${request.url.slice('feishin://'.length)}`; - const response = await net.fetch(filePath); - const contentType = response.headers.get('content-type'); + // protocol.handle('feishin', async (request) => { + // const filePath = `file://${request.url.slice('feishin://'.length)}` + // const response = await net.fetch(filePath) + // const contentType = response.headers.get('content-type') - if (!contentType || !FONT_HEADERS.includes(contentType)) { - getMainWindow()?.webContents.send('custom-font-error', filePath); + // if (!contentType || !FONT_HEADERS.includes(contentType)) { + // getMainWindow()?.webContents.send('custom-font-error', filePath) - return new Response(null, { - status: 403, - statusText: 'Forbidden', - }); - } + // return new Response(null, { + // status: 403, + // statusText: 'Forbidden' + // }) + // } - return response; - }); + // return response + // }) createWindow(); if (store.get('window_enable_tray', true)) { diff --git a/src/main/menu.ts b/src/main/menu.ts index c8c5f77b..f3f12cf0 100644 --- a/src/main/menu.ts +++ b/src/main/menu.ts @@ -1,4 +1,4 @@ -import { app, Menu, shell, BrowserWindow, MenuItemConstructorOptions } from 'electron'; +import { app, BrowserWindow, Menu, MenuItemConstructorOptions, shell } from 'electron'; interface DarwinMenuItemConstructorOptions extends MenuItemConstructorOptions { selector?: string; @@ -12,37 +12,6 @@ export default class MenuBuilder { this.mainWindow = mainWindow; } - buildMenu(): Menu { - if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true') { - this.setupDevelopmentEnvironment(); - } - - const template = - process.platform === 'darwin' - ? this.buildDarwinTemplate() - : this.buildDefaultTemplate(); - - const menu = Menu.buildFromTemplate(template); - Menu.setApplicationMenu(menu); - - return menu; - } - - setupDevelopmentEnvironment(): void { - this.mainWindow.webContents.on('context-menu', (_, props) => { - const { x, y } = props; - - Menu.buildFromTemplate([ - { - click: () => { - this.mainWindow.webContents.inspectElement(x, y); - }, - label: 'Inspect element', - }, - ]).popup({ window: this.mainWindow }); - }); - } - buildDarwinTemplate(): MenuItemConstructorOptions[] { const subMenuAbout: DarwinMenuItemConstructorOptions = { label: 'Electron', @@ -276,4 +245,35 @@ export default class MenuBuilder { return templateDefault; } + + buildMenu(): Menu { + if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true') { + this.setupDevelopmentEnvironment(); + } + + const template = + process.platform === 'darwin' + ? this.buildDarwinTemplate() + : this.buildDefaultTemplate(); + + const menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); + + return menu; + } + + setupDevelopmentEnvironment(): void { + this.mainWindow.webContents.on('context-menu', (_, props) => { + const { x, y } = props; + + Menu.buildFromTemplate([ + { + click: () => { + this.mainWindow.webContents.inspectElement(x, y); + }, + label: 'Inspect element', + }, + ]).popup({ window: this.mainWindow }); + }); + } } diff --git a/src/main/preload.ts b/src/main/preload.ts deleted file mode 100644 index d2183785..00000000 --- a/src/main/preload.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { contextBridge } from 'electron'; -import { browser } from './preload/browser'; -import { discordRpc } from './preload/discord-rpc'; -import { ipc } from './preload/ipc'; -import { localSettings } from './preload/local-settings'; -import { lyrics } from './preload/lyrics'; -import { mpris } from './preload/mpris'; -import { mpvPlayer, mpvPlayerListener } from './preload/mpv-player'; -import { remote } from './preload/remote'; -import { utils } from './preload/utils'; - -contextBridge.exposeInMainWorld('electron', { - browser, - discordRpc, - ipc, - localSettings, - lyrics, - mpris, - mpvPlayer, - mpvPlayerListener, - remote, - utils, -}); diff --git a/src/main/utils.ts b/src/main/utils.ts index aa3196eb..fe5ea808 100644 --- a/src/main/utils.ts +++ b/src/main/utils.ts @@ -1,8 +1,7 @@ -/* eslint import/prefer-default-export: off, import/no-mutable-exports: off */ +import log from 'electron-log/main'; import path from 'path'; import process from 'process'; import { URL } from 'url'; -import log from 'electron-log/main'; export let resolveHtmlPath: (htmlFileName: string) => string; @@ -76,7 +75,7 @@ const logColor = { export const createLog = (data: { message: string; - type: 'debug' | 'verbose' | 'success' | 'error' | 'warning' | 'info'; + type: 'debug' | 'error' | 'info' | 'success' | 'verbose' | 'warning'; }) => { logMethod[data.type](`%c${data.message}`, `color: ${logColor[data.type]}`); }; diff --git a/src/main/preload/browser.ts b/src/preload/browser.ts similarity index 100% rename from src/main/preload/browser.ts rename to src/preload/browser.ts diff --git a/src/main/preload/discord-rpc.ts b/src/preload/discord-rpc.ts similarity index 100% rename from src/main/preload/discord-rpc.ts rename to src/preload/discord-rpc.ts diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts new file mode 100644 index 00000000..caecdb7b --- /dev/null +++ b/src/preload/index.d.ts @@ -0,0 +1,10 @@ +import { ElectronAPI } from '@electron-toolkit/preload'; + +import { PreloadApi } from './index'; + +declare global { + interface Window { + api: PreloadApi; + electron: ElectronAPI; + } +} diff --git a/src/preload/index.ts b/src/preload/index.ts new file mode 100644 index 00000000..7115f7b3 --- /dev/null +++ b/src/preload/index.ts @@ -0,0 +1,45 @@ +import { electronAPI } from '@electron-toolkit/preload'; +import { contextBridge } from 'electron'; + +import { browser } from './browser'; +import { discordRpc } from './discord-rpc'; +import { ipc } from './ipc'; +import { localSettings } from './local-settings'; +import { lyrics } from './lyrics'; +import { mpris } from './mpris'; +import { mpvPlayer, mpvPlayerListener } from './mpv-player'; +import { remote } from './remote'; +import { utils } from './utils'; + +// Custom APIs for renderer +const api = { + browser, + discordRpc, + ipc, + localSettings, + lyrics, + mpris, + mpvPlayer, + mpvPlayerListener, + remote, + utils, +}; + +export type PreloadApi = typeof api; + +// Use `contextBridge` APIs to expose Electron APIs to +// renderer only if context isolation is enabled, otherwise +// just add to the DOM global. +if (process.contextIsolated) { + try { + contextBridge.exposeInMainWorld('electron', electronAPI); + contextBridge.exposeInMainWorld('api', api); + } catch (error) { + console.error(error); + } +} else { + // @ts-ignore (define in dts) + window.electron = electronAPI; + // @ts-ignore (define in dts) + window.api = api; +} diff --git a/src/main/preload/ipc.ts b/src/preload/ipc.ts similarity index 100% rename from src/main/preload/ipc.ts rename to src/preload/ipc.ts diff --git a/src/main/preload/local-settings.ts b/src/preload/local-settings.ts similarity index 77% rename from src/main/preload/local-settings.ts rename to src/preload/local-settings.ts index 5f20e574..986f5203 100644 --- a/src/main/preload/local-settings.ts +++ b/src/preload/local-settings.ts @@ -1,12 +1,11 @@ -import { IpcRendererEvent, ipcRenderer, webFrame } from 'electron'; +import { ipcRenderer, IpcRendererEvent, webFrame } from 'electron'; import Store from 'electron-store'; -import { toServerType, type TitleTheme } from '/@/renderer/types'; const store = new Store(); const set = ( property: string, - value: string | Record | boolean | string[] | undefined, + value: boolean | Record | string | string[] | undefined, ) => { if (value === undefined) { store.delete(property); @@ -32,7 +31,7 @@ const disableMediaKeys = () => { ipcRenderer.send('global-media-keys-disable'); }; -const passwordGet = async (server: string): Promise => { +const passwordGet = async (server: string): Promise => { return ipcRenderer.invoke('password-get', server); }; @@ -56,6 +55,19 @@ const themeSet = (theme: TitleTheme): void => { ipcRenderer.send('theme-set', theme); }; +export const toServerType = (value?: string): null | string => { + switch (value?.toLowerCase()) { + case 'jellyfin': + return 'jellyfin'; + case 'navidrome': + return 'navidrome'; + case 'subsonic': + return 'subsonic'; + default: + return null; + } +}; + const SERVER_TYPE = toServerType(process.env.SERVER_TYPE); const env = { diff --git a/src/main/preload/lyrics.ts b/src/preload/lyrics.ts similarity index 94% rename from src/main/preload/lyrics.ts rename to src/preload/lyrics.ts index 1b6694cc..3c0cbb75 100644 --- a/src/main/preload/lyrics.ts +++ b/src/preload/lyrics.ts @@ -1,11 +1,11 @@ import { ipcRenderer } from 'electron'; + import { InternetProviderLyricSearchResponse, LyricGetQuery, LyricSearchQuery, LyricSource, - QueueSong, -} from '/@/renderer/api/types'; +} from '../main/features/core/lyrics'; const getRemoteLyricsBySong = (song: QueueSong) => { const result = ipcRenderer.invoke('lyric-by-song', song); diff --git a/src/main/preload/mpris.ts b/src/preload/mpris.ts similarity index 88% rename from src/main/preload/mpris.ts rename to src/preload/mpris.ts index 9777201e..0edb90c3 100644 --- a/src/main/preload/mpris.ts +++ b/src/preload/mpris.ts @@ -1,5 +1,4 @@ -import { IpcRendererEvent, ipcRenderer } from 'electron'; -import type { PlayerRepeat } from '/@/renderer/types'; +import { ipcRenderer, IpcRendererEvent } from 'electron'; const updatePosition = (timeSec: number) => { ipcRenderer.send('mpris-update-position', timeSec); diff --git a/src/main/preload/mpv-player.ts b/src/preload/mpv-player.ts similarity index 99% rename from src/main/preload/mpv-player.ts rename to src/preload/mpv-player.ts index e0be6fd9..8370db3c 100644 --- a/src/main/preload/mpv-player.ts +++ b/src/preload/mpv-player.ts @@ -1,5 +1,4 @@ import { ipcRenderer, IpcRendererEvent } from 'electron'; -import { PlayerData } from '/@/renderer/store'; const initialize = (data: { extraParameters?: string[]; properties?: Record }) => { return ipcRenderer.invoke('player-initialize', data); @@ -187,8 +186,8 @@ export const mpvPlayerListener = { rendererNext, rendererPause, rendererPlay, - rendererPlayPause, rendererPlayerFallback, + rendererPlayPause, rendererPrevious, rendererQuit, rendererSkipBackward, diff --git a/src/main/preload/remote.ts b/src/preload/remote.ts similarity index 89% rename from src/main/preload/remote.ts rename to src/preload/remote.ts index a589be68..95f3849f 100644 --- a/src/main/preload/remote.ts +++ b/src/preload/remote.ts @@ -1,6 +1,4 @@ -import { IpcRendererEvent, ipcRenderer } from 'electron'; -import { QueueSong } from '/@/renderer/api/types'; -import { PlayerStatus } from '/@/renderer/types'; +import { ipcRenderer, IpcRendererEvent } from 'electron'; const requestFavorite = ( cb: ( @@ -29,12 +27,12 @@ const requestVolume = (cb: (event: IpcRendererEvent, data: { volume: number }) = ipcRenderer.on('request-volume', cb); }; -const setRemoteEnabled = (enabled: boolean): Promise => { +const setRemoteEnabled = (enabled: boolean): Promise => { const result = ipcRenderer.invoke('remote-enable', enabled); return result; }; -const setRemotePort = (port: number): Promise => { +const setRemotePort = (port: number): Promise => { const result = ipcRenderer.invoke('remote-port', port); return result; }; @@ -56,7 +54,7 @@ const updateSetting = ( port: number, username: string, password: string, -): Promise => { +): Promise => { return ipcRenderer.invoke('remote-settings', enabled, port, username, password); }; diff --git a/src/main/preload/utils.ts b/src/preload/utils.ts similarity index 79% rename from src/main/preload/utils.ts rename to src/preload/utils.ts index bd90f956..17fcfb80 100644 --- a/src/main/preload/utils.ts +++ b/src/preload/utils.ts @@ -1,6 +1,6 @@ -import { IpcRendererEvent, ipcRenderer } from 'electron'; -import { isMacOS, isWindows, isLinux } from '../utils'; -import { PlayerState } from '/@/renderer/store'; +import { ipcRenderer, IpcRendererEvent } from 'electron'; + +import { isLinux, isMacOS, isWindows } from '../main/utils'; const saveQueue = (data: Record) => { ipcRenderer.send('player-save-queue', data); @@ -18,7 +18,7 @@ const onSaveQueue = (cb: (event: IpcRendererEvent) => void) => { ipcRenderer.on('renderer-save-queue', cb); }; -const onRestoreQueue = (cb: (event: IpcRendererEvent, data: Partial) => void) => { +const onRestoreQueue = (cb: (event: IpcRendererEvent, data: Partial) => void) => { ipcRenderer.on('renderer-restore-queue', cb); }; @@ -29,7 +29,7 @@ const playerErrorListener = (cb: (event: IpcRendererEvent, data: { code: number const mainMessageListener = ( cb: ( event: IpcRendererEvent, - data: { message: string; type: 'success' | 'error' | 'warning' | 'info' }, + data: { message: string; type: 'error' | 'info' | 'success' | 'warning' }, ) => void, ) => { ipcRenderer.on('toast-from-main', cb); @@ -40,7 +40,7 @@ const logger = ( event: IpcRendererEvent, data: { message: string; - type: 'debug' | 'verbose' | 'error' | 'warning' | 'info'; + type: 'debug' | 'error' | 'info' | 'verbose' | 'warning'; }, ) => void, ) => { diff --git a/src/renderer/api/controller.ts b/src/renderer/api/controller.ts index 0eb9958e..c42281f9 100644 --- a/src/renderer/api/controller.ts +++ b/src/renderer/api/controller.ts @@ -1,10 +1,11 @@ -import { useAuthStore } from '/@/renderer/store'; -import { toast } from '/@/renderer/components/toast/index'; -import type { ServerType, ControllerEndpoint, AuthenticationResponse } from '/@/renderer/api/types'; +import type { AuthenticationResponse, ControllerEndpoint, ServerType } from '/@/renderer/api/types'; + +import i18n from '/@/i18n/i18n'; +import { JellyfinController } from '/@/renderer/api/jellyfin/jellyfin-controller'; import { NavidromeController } from '/@/renderer/api/navidrome/navidrome-controller'; import { SubsonicController } from '/@/renderer/api/subsonic/subsonic-controller'; -import { JellyfinController } from '/@/renderer/api/jellyfin/jellyfin-controller'; -import i18n from '/@/i18n/i18n'; +import { toast } from '/@/renderer/components/toast/index'; +import { useAuthStore } from '/@/renderer/store'; type ApiController = { jellyfin: ControllerEndpoint; diff --git a/src/renderer/api/jellyfin.types.ts b/src/renderer/api/jellyfin.types.ts index f22febba..216011db 100644 --- a/src/renderer/api/jellyfin.types.ts +++ b/src/renderer/api/jellyfin.types.ts @@ -1,97 +1,56 @@ -export type JFBasePaginatedResponse = { - StartIndex: number; - TotalRecordCount: number; -}; - -export interface JFMusicFolderListResponse extends JFBasePaginatedResponse { - Items: JFMusicFolder[]; +export enum JFAlbumArtistListSort { + ALBUM = 'Album,SortName', + DURATION = 'Runtime,AlbumArtist,Album,SortName', + NAME = 'SortName,Name', + RANDOM = 'Random,SortName', + RECENTLY_ADDED = 'DateCreated,SortName', + RELEASE_DATE = 'PremiereDate,AlbumArtist,Album,SortName', } -export type JFMusicFolderList = JFMusicFolder[]; - -export interface JFGenreListResponse extends JFBasePaginatedResponse { - Items: JFGenre[]; +export enum JFAlbumListSort { + ALBUM_ARTIST = 'AlbumArtist,SortName', + COMMUNITY_RATING = 'CommunityRating,SortName', + CRITIC_RATING = 'CriticRating,SortName', + NAME = 'SortName', + PLAY_COUNT = 'PlayCount', + RANDOM = 'Random,SortName', + RECENTLY_ADDED = 'DateCreated,SortName', + RELEASE_DATE = 'ProductionYear,PremiereDate,SortName', } -export type JFGenreList = JFGenreListResponse; +export enum JFArtistListSort { + ALBUM = 'Album,SortName', + DURATION = 'Runtime,AlbumArtist,Album,SortName', + NAME = 'SortName,Name', + RANDOM = 'Random,SortName', + RECENTLY_ADDED = 'DateCreated,SortName', + RELEASE_DATE = 'PremiereDate,AlbumArtist,Album,SortName', +} + +export enum JFCollectionType { + MUSIC = 'music', + PLAYLISTS = 'playlists', +} + +export enum JFExternalType { + MUSICBRAINZ = 'MusicBrainz', + THEAUDIODB = 'TheAudioDb', +} export enum JFGenreListSort { NAME = 'SortName', } -export type JFAlbumArtistDetailResponse = JFAlbumArtist; - -export type JFAlbumArtistDetail = JFAlbumArtistDetailResponse; - -export interface JFAlbumArtistListResponse extends JFBasePaginatedResponse { - Items: JFAlbumArtist[]; +export enum JFImageType { + LOGO = 'Logo', + PRIMARY = 'Primary', } -export type JFAlbumArtistList = { - items: JFAlbumArtist[]; - startIndex: number; - totalRecordCount: number; -}; - -export interface JFArtistListResponse extends JFBasePaginatedResponse { - Items: JFAlbumArtist[]; +export enum JFItemType { + AUDIO = 'Audio', + MUSICALBUM = 'MusicAlbum', } -export type JFArtistList = JFArtistListResponse; - -export interface JFAlbumListResponse extends JFBasePaginatedResponse { - Items: JFAlbum[]; -} - -export type JFAlbumList = { - items: JFAlbum[]; - startIndex: number; - totalRecordCount: number; -}; - -export type JFAlbumDetailResponse = JFAlbum; - -export type JFAlbumDetail = JFAlbum & { songs?: JFSong[] }; - -export interface JFSongListResponse extends JFBasePaginatedResponse { - Items: JFSong[]; -} - -export type JFSongList = { - items: JFSong[]; - startIndex: number; - totalRecordCount: number; -}; - -export type JFAddToPlaylistResponse = { - added: number; -}; - -export type JFAddToPlaylistParams = { - ids: string[]; - userId: string; -}; - -export type JFAddToPlaylist = null; - -export type JFRemoveFromPlaylistResponse = null; - -export type JFRemoveFromPlaylistParams = { - entryIds: string[]; -}; - -export type JFRemoveFromPlaylist = null; - -export interface JFPlaylistListResponse extends JFBasePaginatedResponse { - Items: JFPlaylist[]; -} - -export type JFPlaylistList = { - items: JFPlaylist[]; - startIndex: number; - totalRecordCount: number; -}; - export enum JFPlaylistListSort { ALBUM_ARTIST = 'AlbumArtist,SortName', DURATION = 'Runtime', @@ -100,124 +59,34 @@ export enum JFPlaylistListSort { SONG_COUNT = 'ChildCount', } -export type JFPlaylistDetailResponse = JFPlaylist; +export enum JFSongListSort { + ALBUM = 'Album,SortName', + ALBUM_ARTIST = 'AlbumArtist,Album,SortName', + ARTIST = 'Artist,Album,SortName', + COMMUNITY_RATING = 'CommunityRating,SortName', + DURATION = 'Runtime,AlbumArtist,Album,SortName', + NAME = 'Name', + PLAY_COUNT = 'PlayCount,SortName', + RANDOM = 'Random,SortName', + RECENTLY_ADDED = 'DateCreated,SortName', + RECENTLY_PLAYED = 'DatePlayed,SortName', + RELEASE_DATE = 'PremiereDate,AlbumArtist,Album,SortName', +} -export type JFPlaylistDetail = JFPlaylist & { songs?: JFSong[] }; +export enum JFSortOrder { + ASC = 'Ascending', + DESC = 'Descending', +} -export type JFPlaylist = { - BackdropImageTags: string[]; - ChannelId: null; - ChildCount?: number; - DateCreated: string; - GenreItems: GenreItem[]; - Genres: string[]; - Id: string; - ImageBlurHashes: ImageBlurHashes; - ImageTags: ImageTags; - IsFolder: boolean; - LocationType: string; - MediaType: string; - Name: string; - Overview?: string; - RunTimeTicks: number; - ServerId: string; - Type: string; - UserData: UserData; +export type JFAddToPlaylist = null; + +export type JFAddToPlaylistParams = { + ids: string[]; + userId: string; }; -export type JFRequestParams = { - albumArtistIds?: string; - artistIds?: string; - enableImageTypes?: string; - enableTotalRecordCount?: boolean; - enableUserData?: boolean; - excludeItemTypes?: string; - fields?: string; - imageTypeLimit?: number; - includeItemTypes?: string; - isFavorite?: boolean; - limit?: number; - parentId?: string; - recursive?: boolean; - searchTerm?: string; - sortBy?: string; - sortOrder?: 'Ascending' | 'Descending'; - startIndex?: number; - userId?: string; -}; - -export type JFMusicFolder = { - BackdropImageTags: string[]; - ChannelId: null; - CollectionType: string; - Id: string; - ImageBlurHashes: ImageBlurHashes; - ImageTags: ImageTags; - IsFolder: boolean; - LocationType: string; - Name: string; - ServerId: string; - Type: string; - UserData: UserData; -}; - -export type JFGenre = { - BackdropImageTags: any[]; - ChannelId: null; - Id: string; - ImageBlurHashes: any; - ImageTags: ImageTags; - LocationType: string; - Name: string; - ServerId: string; - Type: string; -}; - -export type JFAlbumArtist = { - BackdropImageTags: string[]; - ChannelId: null; - DateCreated: string; - ExternalUrls: ExternalURL[]; - GenreItems: GenreItem[]; - Genres: string[]; - Id: string; - ImageBlurHashes: any; - ImageTags: ImageTags; - LocationType: string; - Name: string; - Overview?: string; - RunTimeTicks: number; - ServerId: string; - Type: string; - UserData: { - IsFavorite: boolean; - Key: string; - PlayCount: number; - PlaybackPositionTicks: number; - Played: boolean; - }; -} & { - similarArtists: { - items: JFAlbumArtist[]; - }; -}; - -export type JFArtist = { - BackdropImageTags: string[]; - ChannelId: null; - DateCreated: string; - ExternalUrls: ExternalURL[]; - GenreItems: GenreItem[]; - Genres: string[]; - Id: string; - ImageBlurHashes: any; - ImageTags: string[]; - LocationType: string; - Name: string; - Overview?: string; - RunTimeTicks: number; - ServerId: string; - Type: string; +export type JFAddToPlaylistResponse = { + added: number; }; export type JFAlbum = { @@ -251,6 +120,244 @@ export type JFAlbum = { songs?: JFSong[]; }; +export type JFAlbumArtist = { + BackdropImageTags: string[]; + ChannelId: null; + DateCreated: string; + ExternalUrls: ExternalURL[]; + GenreItems: GenreItem[]; + Genres: string[]; + Id: string; + ImageBlurHashes: any; + ImageTags: ImageTags; + LocationType: string; + Name: string; + Overview?: string; + RunTimeTicks: number; + ServerId: string; + Type: string; + UserData: { + IsFavorite: boolean; + Key: string; + PlaybackPositionTicks: number; + PlayCount: number; + Played: boolean; + }; +} & { + similarArtists: { + items: JFAlbumArtist[]; + }; +}; + +export type JFAlbumArtistDetail = JFAlbumArtistDetailResponse; + +export type JFAlbumArtistDetailResponse = JFAlbumArtist; + +export type JFAlbumArtistList = { + items: JFAlbumArtist[]; + startIndex: number; + totalRecordCount: number; +}; + +export type JFAlbumArtistListParams = JFBaseParams & + JFPaginationParams & { + filters?: string; + genres?: string; + sortBy?: JFAlbumArtistListSort; + years?: string; + }; + +export interface JFAlbumArtistListResponse extends JFBasePaginatedResponse { + Items: JFAlbumArtist[]; +} + +export type JFAlbumDetail = JFAlbum & { songs?: JFSong[] }; + +export type JFAlbumDetailResponse = JFAlbum; + +export type JFAlbumList = { + items: JFAlbum[]; + startIndex: number; + totalRecordCount: number; +}; + +export type JFAlbumListParams = JFBaseParams & + JFPaginationParams & { + albumArtistIds?: string; + artistIds?: string; + filters?: string; + genreIds?: string; + genres?: string; + includeItemTypes: 'MusicAlbum'; + isFavorite?: boolean; + searchTerm?: string; + sortBy?: JFAlbumListSort; + tags?: string; + years?: string; + }; + +export interface JFAlbumListResponse extends JFBasePaginatedResponse { + Items: JFAlbum[]; +} + +export type JFArtist = { + BackdropImageTags: string[]; + ChannelId: null; + DateCreated: string; + ExternalUrls: ExternalURL[]; + GenreItems: GenreItem[]; + Genres: string[]; + Id: string; + ImageBlurHashes: any; + ImageTags: string[]; + LocationType: string; + Name: string; + Overview?: string; + RunTimeTicks: number; + ServerId: string; + Type: string; +}; + +export type JFArtistList = JFArtistListResponse; + +export type JFArtistListParams = JFBaseParams & + JFPaginationParams & { + filters?: string; + genres?: string; + sortBy?: JFArtistListSort; + years?: string; + }; + +export interface JFArtistListResponse extends JFBasePaginatedResponse { + Items: JFAlbumArtist[]; +} + +export interface JFAuthenticate { + AccessToken: string; + ServerId: string; + SessionInfo: SessionInfo; + User: User; +} + +export type JFBasePaginatedResponse = { + StartIndex: number; + TotalRecordCount: number; +}; + +export type JFCreatePlaylist = JFCreatePlaylistResponse; + +export type JFCreatePlaylistResponse = { + Id: string; +}; + +export type JFGenericItem = { + Id: string; + Name: string; +}; + +export type JFGenre = { + BackdropImageTags: any[]; + ChannelId: null; + Id: string; + ImageBlurHashes: any; + ImageTags: ImageTags; + LocationType: string; + Name: string; + ServerId: string; + Type: string; +}; + +export type JFGenreList = JFGenreListResponse; + +export interface JFGenreListResponse extends JFBasePaginatedResponse { + Items: JFGenre[]; +} + +export type JFMusicFolder = { + BackdropImageTags: string[]; + ChannelId: null; + CollectionType: string; + Id: string; + ImageBlurHashes: ImageBlurHashes; + ImageTags: ImageTags; + IsFolder: boolean; + LocationType: string; + Name: string; + ServerId: string; + Type: string; + UserData: UserData; +}; + +export type JFMusicFolderList = JFMusicFolder[]; + +export interface JFMusicFolderListResponse extends JFBasePaginatedResponse { + Items: JFMusicFolder[]; +} + +export type JFPlaylist = { + BackdropImageTags: string[]; + ChannelId: null; + ChildCount?: number; + DateCreated: string; + GenreItems: GenreItem[]; + Genres: string[]; + Id: string; + ImageBlurHashes: ImageBlurHashes; + ImageTags: ImageTags; + IsFolder: boolean; + LocationType: string; + MediaType: string; + Name: string; + Overview?: string; + RunTimeTicks: number; + ServerId: string; + Type: string; + UserData: UserData; +}; + +export type JFPlaylistDetail = JFPlaylist & { songs?: JFSong[] }; + +export type JFPlaylistDetailResponse = JFPlaylist; + +export type JFPlaylistList = { + items: JFPlaylist[]; + startIndex: number; + totalRecordCount: number; +}; + +export interface JFPlaylistListResponse extends JFBasePaginatedResponse { + Items: JFPlaylist[]; +} + +export type JFRemoveFromPlaylist = null; + +export type JFRemoveFromPlaylistParams = { + entryIds: string[]; +}; + +export type JFRemoveFromPlaylistResponse = null; + +export type JFRequestParams = { + albumArtistIds?: string; + artistIds?: string; + enableImageTypes?: string; + enableTotalRecordCount?: boolean; + enableUserData?: boolean; + excludeItemTypes?: string; + fields?: string; + imageTypeLimit?: number; + includeItemTypes?: string; + isFavorite?: boolean; + limit?: number; + parentId?: string; + recursive?: boolean; + searchTerm?: string; + sortBy?: string; + sortOrder?: 'Ascending' | 'Descending'; + startIndex?: number; + userId?: string; +}; + export type JFSong = { Album: string; AlbumArtist: string; @@ -285,23 +392,56 @@ export type JFSong = { UserData?: UserData; }; -type ImageBlurHashes = { - Backdrop?: any; - Logo?: any; - Primary?: any; +export type JFSongList = { + items: JFSong[]; + startIndex: number; + totalRecordCount: number; }; -type ImageTags = { - Logo?: string; - Primary?: string; +export type JFSongListParams = JFBaseParams & + JFPaginationParams & { + albumArtistIds?: string; + albumIds?: string; + artistIds?: string; + contributingArtistIds?: string; + filters?: string; + genreIds?: string; + genres?: string; + ids?: string; + includeItemTypes: 'Audio'; + searchTerm?: string; + sortBy?: JFSongListSort; + years?: string; + }; + +export interface JFSongListResponse extends JFBasePaginatedResponse { + Items: JFSong[]; +} + +type Capabilities = { + PlayableMediaTypes: any[]; + SupportedCommands: any[]; + SupportsContentUploading: boolean; + SupportsMediaControl: boolean; + SupportsPersistentIdentifier: boolean; + SupportsSync: boolean; }; -type UserData = { - IsFavorite: boolean; - Key: string; - PlayCount: number; - PlaybackPositionTicks: number; - Played: boolean; +type Configuration = { + DisplayCollectionsView: boolean; + DisplayMissingEpisodes: boolean; + EnableLocalPassword: boolean; + EnableNextEpisodeAutoPlay: boolean; + GroupedFolders: any[]; + HidePlayedInLatest: boolean; + LatestItemsExcludes: any[]; + MyMediaExcludes: any[]; + OrderedViews: any[]; + PlayDefaultAudioTrack: boolean; + RememberAudioSelections: boolean; + RememberSubtitleSelections: boolean; + SubtitleLanguagePreference: string; + SubtitleMode: string; }; type ExternalURL = { @@ -314,9 +454,32 @@ type GenreItem = { Name: string; }; -export type JFGenericItem = { - Id: string; - Name: string; +type ImageBlurHashes = { + Backdrop?: any; + Logo?: any; + Primary?: any; +}; + +type ImageTags = { + Logo?: string; + Primary?: string; +}; + +type JFBaseParams = { + enableImageTypes?: JFImageType[]; + fields?: string; + imageTypeLimit?: number; + parentId?: string; + recursive?: boolean; + searchTerm?: string; + userId?: string; +}; + +type JFPaginationParams = { + limit?: number; + nameStartsWith?: string; + sortOrder?: JFSortOrder; + startIndex?: number; }; type MediaSources = { @@ -380,32 +543,53 @@ type MediaStream = { Width?: number; }; -export enum JFExternalType { - MUSICBRAINZ = 'MusicBrainz', - THEAUDIODB = 'TheAudioDb', -} +type PlayState = { + CanSeek: boolean; + IsMuted: boolean; + IsPaused: boolean; + RepeatMode: string; +}; -export enum JFImageType { - LOGO = 'Logo', - PRIMARY = 'Primary', -} - -export enum JFItemType { - AUDIO = 'Audio', - MUSICALBUM = 'MusicAlbum', -} - -export enum JFCollectionType { - MUSIC = 'music', - PLAYLISTS = 'playlists', -} - -export interface JFAuthenticate { - AccessToken: string; - ServerId: string; - SessionInfo: SessionInfo; - User: User; -} +type Policy = { + AccessSchedules: any[]; + AuthenticationProviderId: string; + BlockedChannels: any[]; + BlockedMediaFolders: any[]; + BlockedTags: any[]; + BlockUnratedItems: any[]; + EnableAllChannels: boolean; + EnableAllDevices: boolean; + EnableAllFolders: boolean; + EnableAudioPlaybackTranscoding: boolean; + EnableContentDeletion: boolean; + EnableContentDeletionFromFolders: any[]; + EnableContentDownloading: boolean; + EnabledChannels: any[]; + EnabledDevices: any[]; + EnabledFolders: any[]; + EnableLiveTvAccess: boolean; + EnableLiveTvManagement: boolean; + EnableMediaConversion: boolean; + EnableMediaPlayback: boolean; + EnablePlaybackRemuxing: boolean; + EnablePublicSharing: boolean; + EnableRemoteAccess: boolean; + EnableRemoteControlOfOtherUsers: boolean; + EnableSharedDeviceControl: boolean; + EnableSyncTranscoding: boolean; + EnableUserPreferenceAccess: boolean; + EnableVideoPlaybackTranscoding: boolean; + ForceRemoteSourceTranscoding: boolean; + InvalidLoginAttemptCount: number; + IsAdministrator: boolean; + IsDisabled: boolean; + IsHidden: boolean; + LoginAttemptsBeforeLockout: number; + MaxActiveSessions: number; + PasswordResetProviderId: string; + RemoteClientBitrateLimit: number; + SyncPlayAccess: string; +}; type SessionInfo = { AdditionalUsers: any[]; @@ -421,8 +605,8 @@ type SessionInfo = { LastPlaybackCheckIn: string; NowPlayingQueue: any[]; NowPlayingQueueFullItems: any[]; - PlayState: PlayState; PlayableMediaTypes: any[]; + PlayState: PlayState; RemoteEndPoint: string; ServerId: string; SupportedCommands: any[]; @@ -432,22 +616,6 @@ type SessionInfo = { UserName: string; }; -type Capabilities = { - PlayableMediaTypes: any[]; - SupportedCommands: any[]; - SupportsContentUploading: boolean; - SupportsMediaControl: boolean; - SupportsPersistentIdentifier: boolean; - SupportsSync: boolean; -}; - -type PlayState = { - CanSeek: boolean; - IsMuted: boolean; - IsPaused: boolean; - RepeatMode: string; -}; - type User = { Configuration: Configuration; EnableAutoLogin: boolean; @@ -462,178 +630,10 @@ type User = { ServerId: string; }; -type Configuration = { - DisplayCollectionsView: boolean; - DisplayMissingEpisodes: boolean; - EnableLocalPassword: boolean; - EnableNextEpisodeAutoPlay: boolean; - GroupedFolders: any[]; - HidePlayedInLatest: boolean; - LatestItemsExcludes: any[]; - MyMediaExcludes: any[]; - OrderedViews: any[]; - PlayDefaultAudioTrack: boolean; - RememberAudioSelections: boolean; - RememberSubtitleSelections: boolean; - SubtitleLanguagePreference: string; - SubtitleMode: string; +type UserData = { + IsFavorite: boolean; + Key: string; + PlaybackPositionTicks: number; + PlayCount: number; + Played: boolean; }; - -type Policy = { - AccessSchedules: any[]; - AuthenticationProviderId: string; - BlockUnratedItems: any[]; - BlockedChannels: any[]; - BlockedMediaFolders: any[]; - BlockedTags: any[]; - EnableAllChannels: boolean; - EnableAllDevices: boolean; - EnableAllFolders: boolean; - EnableAudioPlaybackTranscoding: boolean; - EnableContentDeletion: boolean; - EnableContentDeletionFromFolders: any[]; - EnableContentDownloading: boolean; - EnableLiveTvAccess: boolean; - EnableLiveTvManagement: boolean; - EnableMediaConversion: boolean; - EnableMediaPlayback: boolean; - EnablePlaybackRemuxing: boolean; - EnablePublicSharing: boolean; - EnableRemoteAccess: boolean; - EnableRemoteControlOfOtherUsers: boolean; - EnableSharedDeviceControl: boolean; - EnableSyncTranscoding: boolean; - EnableUserPreferenceAccess: boolean; - EnableVideoPlaybackTranscoding: boolean; - EnabledChannels: any[]; - EnabledDevices: any[]; - EnabledFolders: any[]; - ForceRemoteSourceTranscoding: boolean; - InvalidLoginAttemptCount: number; - IsAdministrator: boolean; - IsDisabled: boolean; - IsHidden: boolean; - LoginAttemptsBeforeLockout: number; - MaxActiveSessions: number; - PasswordResetProviderId: string; - RemoteClientBitrateLimit: number; - SyncPlayAccess: string; -}; - -type JFBaseParams = { - enableImageTypes?: JFImageType[]; - fields?: string; - imageTypeLimit?: number; - parentId?: string; - recursive?: boolean; - searchTerm?: string; - userId?: string; -}; - -type JFPaginationParams = { - limit?: number; - nameStartsWith?: string; - sortOrder?: JFSortOrder; - startIndex?: number; -}; - -export enum JFSortOrder { - ASC = 'Ascending', - DESC = 'Descending', -} - -export enum JFAlbumListSort { - ALBUM_ARTIST = 'AlbumArtist,SortName', - COMMUNITY_RATING = 'CommunityRating,SortName', - CRITIC_RATING = 'CriticRating,SortName', - NAME = 'SortName', - PLAY_COUNT = 'PlayCount', - RANDOM = 'Random,SortName', - RECENTLY_ADDED = 'DateCreated,SortName', - RELEASE_DATE = 'ProductionYear,PremiereDate,SortName', -} - -export type JFAlbumListParams = { - albumArtistIds?: string; - artistIds?: string; - filters?: string; - genreIds?: string; - genres?: string; - includeItemTypes: 'MusicAlbum'; - isFavorite?: boolean; - searchTerm?: string; - sortBy?: JFAlbumListSort; - tags?: string; - years?: string; -} & JFBaseParams & - JFPaginationParams; - -export enum JFSongListSort { - ALBUM = 'Album,SortName', - ALBUM_ARTIST = 'AlbumArtist,Album,SortName', - ARTIST = 'Artist,Album,SortName', - COMMUNITY_RATING = 'CommunityRating,SortName', - DURATION = 'Runtime,AlbumArtist,Album,SortName', - NAME = 'Name', - PLAY_COUNT = 'PlayCount,SortName', - RANDOM = 'Random,SortName', - RECENTLY_ADDED = 'DateCreated,SortName', - RECENTLY_PLAYED = 'DatePlayed,SortName', - RELEASE_DATE = 'PremiereDate,AlbumArtist,Album,SortName', -} - -export type JFSongListParams = { - albumArtistIds?: string; - albumIds?: string; - artistIds?: string; - contributingArtistIds?: string; - filters?: string; - genreIds?: string; - genres?: string; - ids?: string; - includeItemTypes: 'Audio'; - searchTerm?: string; - sortBy?: JFSongListSort; - years?: string; -} & JFBaseParams & - JFPaginationParams; - -export enum JFAlbumArtistListSort { - ALBUM = 'Album,SortName', - DURATION = 'Runtime,AlbumArtist,Album,SortName', - NAME = 'SortName,Name', - RANDOM = 'Random,SortName', - RECENTLY_ADDED = 'DateCreated,SortName', - RELEASE_DATE = 'PremiereDate,AlbumArtist,Album,SortName', -} - -export type JFAlbumArtistListParams = { - filters?: string; - genres?: string; - sortBy?: JFAlbumArtistListSort; - years?: string; -} & JFBaseParams & - JFPaginationParams; - -export enum JFArtistListSort { - ALBUM = 'Album,SortName', - DURATION = 'Runtime,AlbumArtist,Album,SortName', - NAME = 'SortName,Name', - RANDOM = 'Random,SortName', - RECENTLY_ADDED = 'DateCreated,SortName', - RELEASE_DATE = 'PremiereDate,AlbumArtist,Album,SortName', -} - -export type JFArtistListParams = { - filters?: string; - genres?: string; - sortBy?: JFArtistListSort; - years?: string; -} & JFBaseParams & - JFPaginationParams; - -export type JFCreatePlaylistResponse = { - Id: string; -}; - -export type JFCreatePlaylist = JFCreatePlaylistResponse; diff --git a/src/renderer/api/jellyfin/jellyfin-api.ts b/src/renderer/api/jellyfin/jellyfin-api.ts index acb50b51..82fc61cc 100644 --- a/src/renderer/api/jellyfin/jellyfin-api.ts +++ b/src/renderer/api/jellyfin/jellyfin-api.ts @@ -1,15 +1,17 @@ -import { useAuthStore } from '/@/renderer/store'; -import { jfType } from '/@/renderer/api/jellyfin/jellyfin-types'; import { initClient, initContract } from '@ts-rest/core'; import axios, { AxiosError, AxiosResponse, isAxiosError, Method } from 'axios'; -import qs from 'qs'; -import { ServerListItem } from '/@/renderer/api/types'; import omitBy from 'lodash/omitBy'; +import qs from 'qs'; import { z } from 'zod'; -import { authenticationFailure, getClientType } from '/@/renderer/api/utils'; -import i18n from '/@/i18n/i18n'; + import packageJson from '../../../../package.json'; +import i18n from '/@/i18n/i18n'; +import { jfType } from '/@/renderer/api/jellyfin/jellyfin-types'; +import { ServerListItem } from '/@/renderer/api/types'; +import { authenticationFailure, getClientType } from '/@/renderer/api/utils'; +import { useAuthStore } from '/@/renderer/store'; + const c = initContract(); export const contract = c.router({ @@ -356,14 +358,14 @@ export const createAuthHeader = (): string => { }; export const jfApiClient = (args: { - server: ServerListItem | null; + server: null | ServerListItem; signal?: AbortSignal; url?: string; }) => { - const { server, url, signal } = args; + const { server, signal, url } = args; return initClient(contract, { - api: async ({ path, method, headers, body }) => { + api: async ({ body, headers, method, path }) => { let baseUrl: string | undefined; let token: string | undefined; @@ -395,7 +397,7 @@ export const jfApiClient = (args: { headers: result.headers as any, status: result.status, }; - } catch (e: Error | AxiosError | any) { + } catch (e: any | AxiosError | Error) { if (isAxiosError(e)) { if (e.code === 'ERR_NETWORK') { throw new Error( diff --git a/src/renderer/api/jellyfin/jellyfin-controller.ts b/src/renderer/api/jellyfin/jellyfin-controller.ts index be1136cd..564c6cba 100644 --- a/src/renderer/api/jellyfin/jellyfin-controller.ts +++ b/src/renderer/api/jellyfin/jellyfin-controller.ts @@ -1,23 +1,25 @@ +import chunk from 'lodash/chunk'; +import { z } from 'zod'; + +import { jfNormalize } from './jellyfin-normalize'; + +import { ServerFeature } from '/@/renderer/api/features-types'; +import { JFSongListSort, JFSortOrder } from '/@/renderer/api/jellyfin.types'; +import { jfApiClient } from '/@/renderer/api/jellyfin/jellyfin-api'; +import { jfType } from '/@/renderer/api/jellyfin/jellyfin-types'; import { albumArtistListSortMap, - sortOrderMap, albumListSortMap, - songListSortMap, - playlistListSortMap, - genreListSortMap, - Song, - Played, ControllerEndpoint, + genreListSortMap, LibraryItem, + Played, + playlistListSortMap, + Song, + songListSortMap, + sortOrderMap, } from '/@/renderer/api/types'; -import { jfApiClient } from '/@/renderer/api/jellyfin/jellyfin-api'; -import { jfNormalize } from './jellyfin-normalize'; -import { jfType } from '/@/renderer/api/jellyfin/jellyfin-types'; -import { z } from 'zod'; -import { JFSongListSort, JFSortOrder } from '/@/renderer/api/jellyfin.types'; -import { ServerFeature } from '/@/renderer/api/features-types'; -import { VersionInfo, getFeatures, hasFeature } from '/@/renderer/api/utils'; -import chunk from 'lodash/chunk'; +import { getFeatures, hasFeature, VersionInfo } from '/@/renderer/api/utils'; const formatCommaDelimitedString = (value: string[]) => { return value.join(','); @@ -41,7 +43,7 @@ const VERSION_INFO: VersionInfo = [ export const JellyfinController: ControllerEndpoint = { addToPlaylist: async (args) => { - const { query, body, apiClientProps } = args; + const { apiClientProps, body, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -89,7 +91,7 @@ export const JellyfinController: ControllerEndpoint = { }; }, createFavorite: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -108,7 +110,7 @@ export const JellyfinController: ControllerEndpoint = { return null; }, createPlaylist: async (args) => { - const { body, apiClientProps } = args; + const { apiClientProps, body } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -132,7 +134,7 @@ export const JellyfinController: ControllerEndpoint = { }; }, deleteFavorite: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -151,7 +153,7 @@ export const JellyfinController: ControllerEndpoint = { return null; }, deletePlaylist: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await jfApiClient(apiClientProps).deletePlaylist({ params: { @@ -166,7 +168,7 @@ export const JellyfinController: ControllerEndpoint = { return null; }, getAlbumArtistDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -201,7 +203,7 @@ export const JellyfinController: ControllerEndpoint = { ); }, getAlbumArtistList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await jfApiClient(apiClientProps).getAlbumArtistList({ query: { @@ -236,7 +238,7 @@ export const JellyfinController: ControllerEndpoint = { query: { ...query, limit: 1, startIndex: 0 }, }).then((result) => result!.totalRecordCount!), getAlbumDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -274,7 +276,7 @@ export const JellyfinController: ControllerEndpoint = { ); }, getAlbumList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -334,7 +336,7 @@ export const JellyfinController: ControllerEndpoint = { query: { ...query, limit: 1, startIndex: 0 }, }).then((result) => result!.totalRecordCount!), getArtistList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await jfApiClient(apiClientProps).getArtistList({ query: { @@ -404,7 +406,7 @@ export const JellyfinController: ControllerEndpoint = { }; }, getLyrics: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -453,7 +455,7 @@ export const JellyfinController: ControllerEndpoint = { }; }, getPlaylistDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -477,7 +479,7 @@ export const JellyfinController: ControllerEndpoint = { return jfNormalize.playlist(res.body, apiClientProps.server); }, getPlaylistList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -515,7 +517,7 @@ export const JellyfinController: ControllerEndpoint = { query: { ...query, limit: 1, startIndex: 0 }, }).then((result) => result!.totalRecordCount!), getPlaylistSongList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -547,7 +549,7 @@ export const JellyfinController: ControllerEndpoint = { }; }, getRandomSongList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -668,7 +670,7 @@ export const JellyfinController: ControllerEndpoint = { }, []); }, getSongDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await jfApiClient(apiClientProps).getSongDetail({ params: { @@ -684,7 +686,7 @@ export const JellyfinController: ControllerEndpoint = { return jfNormalize.song(res.body, apiClientProps.server, ''); }, getSongList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -864,7 +866,7 @@ export const JellyfinController: ControllerEndpoint = { }; }, getTranscodingUrl: (args) => { - const { base, format, bitrate } = args.query; + const { base, bitrate, format } = args.query; let url = base.replace('transcodingProtocol=hls', 'transcodingProtocol=http'); if (format) { url = url.replace('audioCodec=aac', `audioCodec=${format}`); @@ -892,7 +894,7 @@ export const JellyfinController: ControllerEndpoint = { } }, removeFromPlaylist: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const chunks = chunk(query.songId, MAX_ITEMS_PER_PLAYLIST_ADD); @@ -914,7 +916,7 @@ export const JellyfinController: ControllerEndpoint = { return null; }, scrobble: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const position = query.position && Math.round(query.position); @@ -978,7 +980,7 @@ export const JellyfinController: ControllerEndpoint = { return null; }, search: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); @@ -1071,7 +1073,7 @@ export const JellyfinController: ControllerEndpoint = { }; }, updatePlaylist: async (args) => { - const { query, body, apiClientProps } = args; + const { apiClientProps, body, query } = args; if (!apiClientProps.server?.userId) { throw new Error('No userId found'); diff --git a/src/renderer/api/jellyfin/jellyfin-normalize.ts b/src/renderer/api/jellyfin/jellyfin-normalize.ts index 5bfd7b25..f61d86bb 100644 --- a/src/renderer/api/jellyfin/jellyfin-normalize.ts +++ b/src/renderer/api/jellyfin/jellyfin-normalize.ts @@ -1,18 +1,19 @@ import { nanoid } from 'nanoid'; import { z } from 'zod'; -import { JFAlbum, JFPlaylist, JFMusicFolder, JFGenre } from '/@/renderer/api/jellyfin.types'; + +import { JFAlbum, JFGenre, JFMusicFolder, JFPlaylist } from '/@/renderer/api/jellyfin.types'; import { jfType } from '/@/renderer/api/jellyfin/jellyfin-types'; import { - Song, - LibraryItem, Album, AlbumArtist, - Playlist, - MusicFolder, Genre, + LibraryItem, + MusicFolder, + Playlist, + RelatedArtist, ServerListItem, ServerType, - RelatedArtist, + Song, } from '/@/renderer/api/types'; const getStreamUrl = (args: { @@ -21,9 +22,9 @@ const getStreamUrl = (args: { eTag?: string; id: string; mediaSourceId?: string; - server: ServerListItem | null; + server: null | ServerListItem; }) => { - const { id, server, deviceId } = args; + const { deviceId, id, server } = args; return ( `${server?.url}/audio` + @@ -122,9 +123,9 @@ const getPlaylistCoverArtUrl = (args: { baseUrl: string; item: JFPlaylist; size: ); }; -type AlbumOrSong = z.infer | z.infer; +type AlbumOrSong = z.infer | z.infer; -const getPeople = (item: AlbumOrSong): Record | null => { +const getPeople = (item: AlbumOrSong): null | Record => { if (item.People) { const participants: Record = {}; @@ -151,7 +152,7 @@ const getPeople = (item: AlbumOrSong): Record | null => return null; }; -const getTags = (item: AlbumOrSong): Record | null => { +const getTags = (item: AlbumOrSong): null | Record => { if (item.Tags) { const tags: Record = {}; for (const tag of item.Tags) { @@ -166,7 +167,7 @@ const getTags = (item: AlbumOrSong): Record | null => { const normalizeSong = ( item: z.infer, - server: ServerListItem | null, + server: null | ServerListItem, deviceId: string, imageSize?: number, ): Song => { @@ -252,7 +253,7 @@ const normalizeSong = ( const normalizeAlbum = ( item: z.infer, - server: ServerListItem | null, + server: null | ServerListItem, imageSize?: number, ): Album => { return { @@ -312,7 +313,7 @@ const normalizeAlbumArtist = ( item: z.infer & { similarArtists?: z.infer; }, - server: ServerListItem | null, + server: null | ServerListItem, imageSize?: number, ): AlbumArtist => { const similarArtists = @@ -361,7 +362,7 @@ const normalizeAlbumArtist = ( const normalizePlaylist = ( item: z.infer, - server: ServerListItem | null, + server: null | ServerListItem, imageSize?: number, ): Playlist => { const imageUrl = getPlaylistCoverArtUrl({ @@ -445,7 +446,7 @@ const getGenreCoverArtUrl = (args: { ); }; -const normalizeGenre = (item: JFGenre, server: ServerListItem | null): Genre => { +const normalizeGenre = (item: JFGenre, server: null | ServerListItem): Genre => { return { albumCount: undefined, id: item.Id, diff --git a/src/renderer/api/jellyfin/jellyfin-types.ts b/src/renderer/api/jellyfin/jellyfin-types.ts index 4b3e80f4..074a71ba 100644 --- a/src/renderer/api/jellyfin/jellyfin-types.ts +++ b/src/renderer/api/jellyfin/jellyfin-types.ts @@ -95,8 +95,8 @@ const imageBlurHashes = z.object({ const userData = z.object({ IsFavorite: z.boolean(), Key: z.string(), - PlayCount: z.number(), PlaybackPositionTicks: z.number(), + PlayCount: z.number(), Played: z.boolean(), }); @@ -187,13 +187,13 @@ const sessionInfo = z.object({ LastPlaybackCheckIn: z.string(), NowPlayingQueue: z.array(z.any()), NowPlayingQueueFullItems: z.array(z.any()), + PlayableMediaTypes: z.array(z.any()), PlayState: z.object({ CanSeek: z.boolean(), IsMuted: z.boolean(), IsPaused: z.boolean(), RepeatMode: z.string(), }), - PlayableMediaTypes: z.array(z.any()), RemoteEndPoint: z.string(), ServerId: z.string(), SupportedCommands: z.array(z.any()), @@ -223,10 +223,10 @@ const configuration = z.object({ const policy = z.object({ AccessSchedules: z.array(z.any()), AuthenticationProviderId: z.string(), - BlockUnratedItems: z.array(z.any()), BlockedChannels: z.array(z.any()), BlockedMediaFolders: z.array(z.any()), BlockedTags: z.array(z.any()), + BlockUnratedItems: z.array(z.any()), EnableAllChannels: z.boolean(), EnableAllDevices: z.boolean(), EnableAllFolders: z.boolean(), @@ -234,6 +234,9 @@ const policy = z.object({ EnableContentDeletion: z.boolean(), EnableContentDeletionFromFolders: z.array(z.any()), EnableContentDownloading: z.boolean(), + EnabledChannels: z.array(z.any()), + EnabledDevices: z.array(z.any()), + EnabledFolders: z.array(z.any()), EnableLiveTvAccess: z.boolean(), EnableLiveTvManagement: z.boolean(), EnableMediaConversion: z.boolean(), @@ -246,9 +249,6 @@ const policy = z.object({ EnableSyncTranscoding: z.boolean(), EnableUserPreferenceAccess: z.boolean(), EnableVideoPlaybackTranscoding: z.boolean(), - EnabledChannels: z.array(z.any()), - EnabledDevices: z.array(z.any()), - EnabledFolders: z.array(z.any()), ForceRemoteSourceTranscoding: z.boolean(), InvalidLoginAttemptCount: z.number(), IsAdministrator: z.boolean(), @@ -414,8 +414,8 @@ const song = z.object({ ImageTags: imageTags, IndexNumber: z.number(), IsFolder: z.boolean(), - LUFS: z.number().optional(), LocationType: z.string(), + LUFS: z.number().optional(), MediaSources: z.array(mediaSources), MediaType: z.string(), Name: z.string(), @@ -654,8 +654,8 @@ const favorite = z.object({ Key: z.string(), LastPlayedDate: z.string(), Likes: z.boolean(), - PlayCount: z.number(), PlaybackPositionTicks: z.number(), + PlayCount: z.number(), Played: z.boolean(), PlayedPercentage: z.number(), Rating: z.number(), diff --git a/src/renderer/api/navidrome.types.ts b/src/renderer/api/navidrome.types.ts index 81eef3a0..15473f6a 100644 --- a/src/renderer/api/navidrome.types.ts +++ b/src/renderer/api/navidrome.types.ts @@ -1,30 +1,77 @@ import { SSArtistInfo } from '/@/renderer/api/subsonic.types'; -export type NDAuthenticate = { - id: string; - isAdmin: boolean; - name: string; - subsonicSalt: string; - subsonicToken: string; - token: string; - username: string; +export enum NDAlbumArtistListSort { + ALBUM_COUNT = 'albumCount', + FAVORITED = 'starred_at', + NAME = 'name', + PLAY_COUNT = 'playCount', + RATING = 'rating', + SONG_COUNT = 'songCount', +} + +export enum NDAlbumListSort { + ALBUM_ARTIST = 'album_artist', + ARTIST = 'artist', + DURATION = 'duration', + NAME = 'name', + PLAY_COUNT = 'play_count', + PLAY_DATE = 'play_date', + RANDOM = 'random', + RATING = 'rating', + RECENTLY_ADDED = 'recently_added', + SONG_COUNT = 'songCount', + STARRED = 'starred_at', + YEAR = 'max_year', +} + +export enum NDGenreListSort { + NAME = 'name', +} + +export enum NDPlaylistListSort { + DURATION = 'duration', + NAME = 'name', + OWNER = 'owner_name', + PUBLIC = 'public', + SONG_COUNT = 'songCount', + UPDATED_AT = 'updatedAt', +} + +export enum NDSongListSort { + ALBUM = 'album', + ALBUM_ARTIST = 'order_album_artist_name', + ALBUM_SONGS = 'album', + ARTIST = 'artist', + BPM = 'bpm', + CHANNELS = 'channels', + COMMENT = 'comment', + DURATION = 'duration', + FAVORITED = 'starred_at', + GENRE = 'genre', + ID = 'id', + PLAY_COUNT = 'playCount', + PLAY_DATE = 'playDate', + RANDOM = 'random', + RATING = 'rating', + RECENTLY_ADDED = 'createdAt', + TITLE = 'title', + TRACK = 'track', + YEAR = 'year', +} + +export enum NDSortOrder { + ASC = 'ASC', + DESC = 'DESC', +} + +export type NDAddToPlaylist = null; + +export type NDAddToPlaylistBody = { + ids: string[]; }; -export type NDUser = { - createdAt: string; - email: string; - id: string; - isAdmin: boolean; - lastAccessAt: string; - lastLoginAt: string; - name: string; - updatedAt: string; - userName: string; -}; - -export type NDGenre = { - id: string; - name: string; +export type NDAddToPlaylistResponse = { + added: number; }; export type NDAlbum = { @@ -61,6 +108,193 @@ export type NDAlbum = { updatedAt: string; } & { songs?: NDSong[] }; +export type NDAlbumArtist = { + albumCount: number; + biography: string; + externalInfoUpdatedAt: string; + externalUrl: string; + fullText: string; + genres: NDGenre[]; + id: string; + largeImageUrl?: string; + mbzArtistId: string; + mediumImageUrl?: string; + name: string; + orderArtistName: string; + playCount: number; + playDate: string; + rating: number; + size: number; + smallImageUrl?: string; + songCount: number; + starred: boolean; + starredAt: string; +} & { + similarArtists?: SSArtistInfo['similarArtist']; +}; + +export type NDAlbumArtistDetail = NDAlbumArtist; + +export type NDAlbumArtistDetailResponse = NDAlbumArtist; + +export type NDAlbumArtistList = { + items: NDAlbumArtist[]; + startIndex: number; + totalRecordCount: number; +}; + +export type NDAlbumArtistListParams = NDOrder & + NDPagination & { + _sort?: NDAlbumArtistListSort; + genre_id?: string; + starred?: boolean; + }; + +export type NDAlbumDetail = NDAlbum & { songs?: NDSongListResponse }; + +export type NDAlbumDetailResponse = NDAlbum; + +export type NDAlbumList = { + items: NDAlbum[]; + startIndex: number; + totalRecordCount: number; +}; + +export type NDAlbumListParams = NDOrder & + NDPagination & { + _sort?: NDAlbumListSort; + album_id?: string; + artist_id?: string; + compilation?: boolean; + genre_id?: string; + has_rating?: boolean; + id?: string; + name?: string; + recently_played?: boolean; + starred?: boolean; + year?: number; + }; + +export type NDAlbumListResponse = NDAlbum[]; + +export type NDArtistListResponse = NDAlbumArtist[]; + +export type NDAuthenticate = { + id: string; + isAdmin: boolean; + name: string; + subsonicSalt: string; + subsonicToken: string; + token: string; + username: string; +}; + +export type NDAuthenticationResponse = NDAuthenticate; + +export type NDCreatePlaylist = NDCreatePlaylistResponse; + +export type NDCreatePlaylistParams = { + comment?: string; + name: string; + public?: boolean; + rules?: null | Record; +}; + +export type NDCreatePlaylistResponse = { + id: string; +}; + +export type NDDeletePlaylist = NDDeletePlaylistResponse; + +export type NDDeletePlaylistParams = { + id: string; +}; + +export type NDDeletePlaylistResponse = null; + +export type NDGenre = { + id: string; + name: string; +}; + +export type NDGenreList = NDGenre[]; + +export type NDGenreListParams = NDOrder & + NDPagination & { + _sort?: NDGenreListSort; + id?: string; + }; + +export type NDGenreListResponse = NDGenre[]; + +export type NDOrder = { + _order?: NDSortOrder; +}; + +export type NDPagination = { + _end?: number; + _start?: number; +}; + +export type NDPlaylist = { + comment: string; + createdAt: string; + duration: number; + evaluatedAt: string; + id: string; + name: string; + ownerId: string; + ownerName: string; + path: string; + public: boolean; + rules: null | Record; + size: number; + songCount: number; + sync: boolean; + updatedAt: string; +}; + +export type NDPlaylistDetail = NDPlaylist; + +export type NDPlaylistDetailResponse = NDPlaylist; + +export type NDPlaylistList = { + items: NDPlaylist[]; + startIndex: number; + totalRecordCount: number; +}; + +export type NDPlaylistListParams = NDOrder & + NDPagination & { + _sort?: NDPlaylistListSort; + owner_id?: string; + }; + +export type NDPlaylistListResponse = NDPlaylist[]; + +export type NDPlaylistSong = NDSong & { + mediaFileId: string; + playlistId: string; +}; + +export type NDPlaylistSongList = { + items: NDPlaylistSong[]; + startIndex: number; + totalRecordCount: number; +}; + +export type NDPlaylistSongListResponse = NDPlaylistSong[]; + +export type NDRemoveFromPlaylist = null; + +export type NDRemoveFromPlaylistParams = { + id: string[]; +}; + +export type NDRemoveFromPlaylistResponse = { + ids: string[]; +}; + export type NDSong = { album: string; albumArtist: string; @@ -107,275 +341,41 @@ export type NDSong = { year: number; }; -export type NDAlbumArtist = { - albumCount: number; - biography: string; - externalInfoUpdatedAt: string; - externalUrl: string; - fullText: string; - genres: NDGenre[]; - id: string; - largeImageUrl?: string; - mbzArtistId: string; - mediumImageUrl?: string; - name: string; - orderArtistName: string; - playCount: number; - playDate: string; - rating: number; - size: number; - smallImageUrl?: string; - songCount: number; - starred: boolean; - starredAt: string; -} & { - similarArtists?: SSArtistInfo['similarArtist']; -}; - -export type NDAuthenticationResponse = NDAuthenticate; - -export type NDAlbumArtistList = { - items: NDAlbumArtist[]; - startIndex: number; - totalRecordCount: number; -}; - -export type NDAlbumArtistDetail = NDAlbumArtist; - -export type NDAlbumArtistDetailResponse = NDAlbumArtist; - -export type NDGenreList = NDGenre[]; - -export type NDGenreListResponse = NDGenre[]; - -export type NDAlbumDetailResponse = NDAlbum; - -export type NDAlbumDetail = NDAlbum & { songs?: NDSongListResponse }; - -export type NDAlbumListResponse = NDAlbum[]; - -export type NDAlbumList = { - items: NDAlbum[]; - startIndex: number; - totalRecordCount: number; -}; - export type NDSongDetail = NDSong; export type NDSongDetailResponse = NDSong; -export type NDSongListResponse = NDSong[]; - export type NDSongList = { items: NDSong[]; startIndex: number; totalRecordCount: number; }; -export type NDArtistListResponse = NDAlbumArtist[]; +export type NDSongListParams = NDOrder & + NDPagination & { + _sort?: NDSongListSort; + album_id?: string[]; + artist_id?: string[]; + genre_id?: string; + starred?: boolean; + }; -export type NDPagination = { - _end?: number; - _start?: number; -}; - -export enum NDSortOrder { - ASC = 'ASC', - DESC = 'DESC', -} - -export type NDOrder = { - _order?: NDSortOrder; -}; - -export enum NDGenreListSort { - NAME = 'name', -} - -export type NDGenreListParams = { - _sort?: NDGenreListSort; - id?: string; -} & NDPagination & - NDOrder; - -export enum NDAlbumListSort { - ALBUM_ARTIST = 'album_artist', - ARTIST = 'artist', - DURATION = 'duration', - NAME = 'name', - PLAY_COUNT = 'play_count', - PLAY_DATE = 'play_date', - RANDOM = 'random', - RATING = 'rating', - RECENTLY_ADDED = 'recently_added', - SONG_COUNT = 'songCount', - STARRED = 'starred_at', - YEAR = 'max_year', -} - -export type NDAlbumListParams = { - _sort?: NDAlbumListSort; - album_id?: string; - artist_id?: string; - compilation?: boolean; - genre_id?: string; - has_rating?: boolean; - id?: string; - name?: string; - recently_played?: boolean; - starred?: boolean; - year?: number; -} & NDPagination & - NDOrder; - -export enum NDSongListSort { - ALBUM = 'album', - ALBUM_ARTIST = 'order_album_artist_name', - ALBUM_SONGS = 'album', - ARTIST = 'artist', - BPM = 'bpm', - CHANNELS = 'channels', - COMMENT = 'comment', - DURATION = 'duration', - FAVORITED = 'starred_at', - GENRE = 'genre', - ID = 'id', - PLAY_COUNT = 'playCount', - PLAY_DATE = 'playDate', - RANDOM = 'random', - RATING = 'rating', - RECENTLY_ADDED = 'createdAt', - TITLE = 'title', - TRACK = 'track', - YEAR = 'year', -} - -export type NDSongListParams = { - _sort?: NDSongListSort; - album_id?: string[]; - artist_id?: string[]; - genre_id?: string; - starred?: boolean; -} & NDPagination & - NDOrder; - -export enum NDAlbumArtistListSort { - ALBUM_COUNT = 'albumCount', - FAVORITED = 'starred_at', - NAME = 'name', - PLAY_COUNT = 'playCount', - RATING = 'rating', - SONG_COUNT = 'songCount', -} - -export type NDAlbumArtistListParams = { - _sort?: NDAlbumArtistListSort; - genre_id?: string; - starred?: boolean; -} & NDPagination & - NDOrder; - -export type NDAddToPlaylistResponse = { - added: number; -}; - -export type NDAddToPlaylistBody = { - ids: string[]; -}; - -export type NDAddToPlaylist = null; - -export type NDRemoveFromPlaylistResponse = { - ids: string[]; -}; - -export type NDRemoveFromPlaylistParams = { - id: string[]; -}; - -export type NDRemoveFromPlaylist = null; - -export type NDCreatePlaylistParams = { - comment?: string; - name: string; - public?: boolean; - rules?: Record | null; -}; - -export type NDCreatePlaylistResponse = { - id: string; -}; - -export type NDCreatePlaylist = NDCreatePlaylistResponse; +export type NDSongListResponse = NDSong[]; export type NDUpdatePlaylistParams = Partial; export type NDUpdatePlaylistResponse = NDPlaylist; -export type NDDeletePlaylistParams = { - id: string; -}; - -export type NDDeletePlaylistResponse = null; - -export type NDDeletePlaylist = NDDeletePlaylistResponse; - -export type NDPlaylist = { - comment: string; +export type NDUser = { createdAt: string; - duration: number; - evaluatedAt: string; + email: string; id: string; + isAdmin: boolean; + lastAccessAt: string; + lastLoginAt: string; name: string; - ownerId: string; - ownerName: string; - path: string; - public: boolean; - rules: Record | null; - size: number; - songCount: number; - sync: boolean; updatedAt: string; -}; - -export type NDPlaylistDetail = NDPlaylist; - -export type NDPlaylistDetailResponse = NDPlaylist; - -export type NDPlaylistList = { - items: NDPlaylist[]; - startIndex: number; - totalRecordCount: number; -}; - -export type NDPlaylistListResponse = NDPlaylist[]; - -export enum NDPlaylistListSort { - DURATION = 'duration', - NAME = 'name', - OWNER = 'owner_name', - PUBLIC = 'public', - SONG_COUNT = 'songCount', - UPDATED_AT = 'updatedAt', -} - -export type NDPlaylistListParams = { - _sort?: NDPlaylistListSort; - owner_id?: string; -} & NDPagination & - NDOrder; - -export type NDPlaylistSong = NDSong & { - mediaFileId: string; - playlistId: string; -}; - -export type NDPlaylistSongListResponse = NDPlaylistSong[]; - -export type NDPlaylistSongList = { - items: NDPlaylistSong[]; - startIndex: number; - totalRecordCount: number; + userName: string; }; export const NDSongQueryFields = [ @@ -515,12 +515,9 @@ export const NDSongQueryNumberOperators = [ { label: 'is in the range', value: 'inTheRange' }, ]; -export type NDUserListParams = { - _sort?: NDUserListSort; -} & NDPagination & - NDOrder; - -export type NDUserListResponse = NDUser[]; +export enum NDUserListSort { + NAME = 'name', +} export type NDUserList = { items: NDUser[]; @@ -528,6 +525,9 @@ export type NDUserList = { totalRecordCount: number; }; -export enum NDUserListSort { - NAME = 'name', -} +export type NDUserListParams = NDOrder & + NDPagination & { + _sort?: NDUserListSort; + }; + +export type NDUserListResponse = NDUser[]; diff --git a/src/renderer/api/navidrome/navidrome-api.ts b/src/renderer/api/navidrome/navidrome-api.ts index 8e5e7529..551d5bea 100644 --- a/src/renderer/api/navidrome/navidrome-api.ts +++ b/src/renderer/api/navidrome/navidrome-api.ts @@ -1,17 +1,19 @@ import { initClient, initContract } from '@ts-rest/core'; -import axios, { Method, AxiosError, AxiosResponse, isAxiosError } from 'axios'; +import axios, { AxiosError, AxiosResponse, isAxiosError, Method } from 'axios'; import isElectron from 'is-electron'; import debounce from 'lodash/debounce'; import omitBy from 'lodash/omitBy'; import qs from 'qs'; -import { ndType } from './navidrome-types'; -import { authenticationFailure, resultWithHeaders } from '/@/renderer/api/utils'; -import { useAuthStore } from '/@/renderer/store'; -import { ServerListItem } from '/@/renderer/api/types'; -import { toast } from '/@/renderer/components/toast'; -import i18n from '/@/i18n/i18n'; -const localSettings = isElectron() ? window.electron.localSettings : null; +import { ndType } from './navidrome-types'; + +import i18n from '/@/i18n/i18n'; +import { ServerListItem } from '/@/renderer/api/types'; +import { authenticationFailure, resultWithHeaders } from '/@/renderer/api/utils'; +import { toast } from '/@/renderer/components/toast'; +import { useAuthStore } from '/@/renderer/store'; + +const localSettings = isElectron() ? window.api.localSettings : null; const c = initContract(); @@ -275,7 +277,7 @@ axiosClient.interceptors.response.use( // eslint-disable-next-line promise/no-promise-in-callback return localSettings .passwordGet(currentServer.id) - .then(async (password: string | null) => { + .then(async (password: null | string) => { authSuccess = false; if (password === null) { @@ -367,14 +369,14 @@ axiosClient.interceptors.response.use( ); export const ndApiClient = (args: { - server: ServerListItem | null; + server: null | ServerListItem; signal?: AbortSignal; url?: string; }) => { - const { server, url, signal } = args; + const { server, signal, url } = args; return initClient(contract, { - api: async ({ path, method, headers, body }) => { + api: async ({ body, headers, method, path }) => { let baseUrl: string | undefined; let token: string | undefined; @@ -406,7 +408,7 @@ export const ndApiClient = (args: { headers: result.headers as any, status: result.status, }; - } catch (e: Error | AxiosError | any) { + } catch (e: any | AxiosError | Error) { if (isAxiosError(e)) { if (e.code === 'ERR_NETWORK') { throw new Error( diff --git a/src/renderer/api/navidrome/navidrome-controller.ts b/src/renderer/api/navidrome/navidrome-controller.ts index 2d50be8c..84b2b986 100644 --- a/src/renderer/api/navidrome/navidrome-controller.ts +++ b/src/renderer/api/navidrome/navidrome-controller.ts @@ -1,28 +1,29 @@ +import { + albumArtistListSortMap, + albumListSortMap, + AuthenticationResponse, + ControllerEndpoint, + genreListSortMap, + playlistListSortMap, + PlaylistSongListArgs, + PlaylistSongListResponse, + ServerListItem, + Song, + songListSortMap, + sortOrderMap, + userListSortMap, +} from '../types'; + +import { ServerFeature, ServerFeatures } from '/@/renderer/api/features-types'; +import { NDSongListSort } from '/@/renderer/api/navidrome.types'; import { ndApiClient } from '/@/renderer/api/navidrome/navidrome-api'; import { ndNormalize } from '/@/renderer/api/navidrome/navidrome-normalize'; import { ndType } from '/@/renderer/api/navidrome/navidrome-types'; import { ssApiClient } from '/@/renderer/api/subsonic/subsonic-api'; -import { - albumArtistListSortMap, - sortOrderMap, - AuthenticationResponse, - userListSortMap, - albumListSortMap, - songListSortMap, - playlistListSortMap, - PlaylistSongListArgs, - PlaylistSongListResponse, - genreListSortMap, - Song, - ControllerEndpoint, - ServerListItem, -} from '../types'; -import { VersionInfo, getFeatures, hasFeature } from '/@/renderer/api/utils'; -import { ServerFeature, ServerFeatures } from '/@/renderer/api/features-types'; -import { SubsonicExtensions } from '/@/renderer/api/subsonic/subsonic-types'; -import { NDSongListSort } from '/@/renderer/api/navidrome.types'; -import { ssNormalize } from '/@/renderer/api/subsonic/subsonic-normalize'; import { SubsonicController } from '/@/renderer/api/subsonic/subsonic-controller'; +import { ssNormalize } from '/@/renderer/api/subsonic/subsonic-normalize'; +import { SubsonicExtensions } from '/@/renderer/api/subsonic/subsonic-types'; +import { getFeatures, hasFeature, VersionInfo } from '/@/renderer/api/utils'; const VERSION_INFO: VersionInfo = [ ['0.55.0', { [ServerFeature.BFR]: [1] }], @@ -48,7 +49,7 @@ const NAVIDROME_ROLES: Array = [ const EXCLUDED_TAGS = new Set(['disctotal', 'genre', 'tracktotal']); -const excludeMissing = (server: ServerListItem | null) => { +const excludeMissing = (server: null | ServerListItem) => { if (hasFeature(server, ServerFeature.BFR)) { return { missing: false }; } @@ -58,7 +59,7 @@ const excludeMissing = (server: ServerListItem | null) => { export const NavidromeController: ControllerEndpoint = { addToPlaylist: async (args) => { - const { body, query, apiClientProps } = args; + const { apiClientProps, body, query } = args; const res = await ndApiClient(apiClientProps).addToPlaylist({ body: { @@ -98,7 +99,7 @@ export const NavidromeController: ControllerEndpoint = { }, createFavorite: SubsonicController.createFavorite, createPlaylist: async (args) => { - const { body, apiClientProps } = args; + const { apiClientProps, body } = args; const res = await ndApiClient(apiClientProps).createPlaylist({ body: { @@ -120,7 +121,7 @@ export const NavidromeController: ControllerEndpoint = { }, deleteFavorite: SubsonicController.deleteFavorite, deletePlaylist: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).deletePlaylist({ params: { @@ -135,7 +136,7 @@ export const NavidromeController: ControllerEndpoint = { return null; }, getAlbumArtistDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).getAlbumArtistDetail({ params: { @@ -176,7 +177,7 @@ export const NavidromeController: ControllerEndpoint = { ); }, getAlbumArtistList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).getAlbumArtistList({ query: { @@ -217,7 +218,7 @@ export const NavidromeController: ControllerEndpoint = { query: { ...query, limit: 1, startIndex: 0 }, }).then((result) => result!.totalRecordCount!), getAlbumDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const albumRes = await ndApiClient(apiClientProps).getAlbumDetail({ params: { @@ -245,7 +246,7 @@ export const NavidromeController: ControllerEndpoint = { ); }, getAlbumInfo: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const albumInfo = await ssApiClient(apiClientProps).getAlbumInfo2({ query: { @@ -265,7 +266,7 @@ export const NavidromeController: ControllerEndpoint = { }; }, getAlbumList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).getAlbumList({ query: { @@ -299,7 +300,7 @@ export const NavidromeController: ControllerEndpoint = { query: { ...query, limit: 1, startIndex: 0 }, }).then((result) => result!.totalRecordCount!), getArtistList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).getAlbumArtistList({ query: { @@ -341,7 +342,7 @@ export const NavidromeController: ControllerEndpoint = { }).then((result) => result!.totalRecordCount!), getDownloadUrl: SubsonicController.getDownloadUrl, getGenreList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).getGenreList({ query: { @@ -366,7 +367,7 @@ export const NavidromeController: ControllerEndpoint = { getLyrics: SubsonicController.getLyrics, getMusicFolderList: SubsonicController.getMusicFolderList, getPlaylistDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).getPlaylistDetail({ params: { @@ -381,7 +382,7 @@ export const NavidromeController: ControllerEndpoint = { return ndNormalize.playlist(res.body.data, apiClientProps.server); }, getPlaylistList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const customQuery = query._custom?.navidrome; // Smart playlists only became available in 0.48.0. Do not filter for previous versions @@ -420,7 +421,7 @@ export const NavidromeController: ControllerEndpoint = { query: { ...query, limit: 1, startIndex: 0 }, }).then((result) => result!.totalRecordCount!), getPlaylistSongList: async (args: PlaylistSongListArgs): Promise => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).getPlaylistSongList({ params: { @@ -548,7 +549,7 @@ export const NavidromeController: ControllerEndpoint = { }, []); }, getSongDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).getSongDetail({ params: { @@ -563,7 +564,7 @@ export const NavidromeController: ControllerEndpoint = { return ndNormalize.song(res.body.data, apiClientProps.server); }, getSongList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).getSongList({ query: { @@ -642,7 +643,7 @@ export const NavidromeController: ControllerEndpoint = { getTopSongs: SubsonicController.getTopSongs, getTranscodingUrl: SubsonicController.getTranscodingUrl, getUserList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).getUserList({ query: { @@ -682,7 +683,7 @@ export const NavidromeController: ControllerEndpoint = { } }, removeFromPlaylist: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ndApiClient(apiClientProps).removeFromPlaylist({ params: { @@ -703,7 +704,7 @@ export const NavidromeController: ControllerEndpoint = { search: SubsonicController.search, setRating: SubsonicController.setRating, shareItem: async (args) => { - const { body, apiClientProps } = args; + const { apiClientProps, body } = args; const res = await ndApiClient(apiClientProps).shareItem({ body: { @@ -724,7 +725,7 @@ export const NavidromeController: ControllerEndpoint = { }; }, updatePlaylist: async (args) => { - const { query, body, apiClientProps } = args; + const { apiClientProps, body, query } = args; const res = await ndApiClient(apiClientProps).updatePlaylist({ body: { diff --git a/src/renderer/api/navidrome/navidrome-normalize.ts b/src/renderer/api/navidrome/navidrome-normalize.ts index d5f4f4ab..70d69cee 100644 --- a/src/renderer/api/navidrome/navidrome-normalize.ts +++ b/src/renderer/api/navidrome/navidrome-normalize.ts @@ -1,22 +1,24 @@ import { nanoid } from 'nanoid'; +import z from 'zod'; + +import { ndType } from './navidrome-types'; + +import { NDGenre } from '/@/renderer/api/navidrome.types'; +import { ssType } from '/@/renderer/api/subsonic/subsonic-types'; import { - Song, - LibraryItem, Album, - Playlist, - User, AlbumArtist, Genre, + LibraryItem, + Playlist, + RelatedArtist, ServerListItem, ServerType, - RelatedArtist, + Song, + User, } from '/@/renderer/api/types'; -import z from 'zod'; -import { ndType } from './navidrome-types'; -import { ssType } from '/@/renderer/api/subsonic/subsonic-types'; -import { NDGenre } from '/@/renderer/api/navidrome.types'; -const getImageUrl = (args: { url: string | null }) => { +const getImageUrl = (args: { url: null | string }) => { const { url } = args; if (url === '/app/artist-placeholder.webp') { return null; @@ -51,19 +53,19 @@ interface WithDate { playDate?: string; } -const normalizePlayDate = (item: WithDate): string | null => { +const normalizePlayDate = (item: WithDate): null | string => { return !item.playDate || item.playDate.includes('0001-') ? null : item.playDate; }; const getArtists = ( item: - | z.infer + | z.infer | z.infer - | z.infer, + | z.infer, ) => { let albumArtists: RelatedArtist[] | undefined; let artists: RelatedArtist[] | undefined; - let participants: Record | null = null; + let participants: null | Record = null; if (item.participants) { participants = {}; @@ -120,8 +122,8 @@ const getArtists = ( }; const normalizeSong = ( - item: z.infer | z.infer, - server: ServerListItem | null, + item: z.infer | z.infer, + server: null | ServerListItem, imageSize?: number, ): Song => { let id; @@ -204,7 +206,7 @@ const normalizeAlbum = ( item: z.infer & { songs?: z.infer; }, - server: ServerListItem | null, + server: null | ServerListItem, imageSize?: number, ): Album => { const imageUrl = getCoverArtUrl({ @@ -268,7 +270,7 @@ const normalizeAlbumArtist = ( item: z.infer & { similarArtists?: z.infer['artistInfo']['similarArtist']; }, - server: ServerListItem | null, + server: null | ServerListItem, ): AlbumArtist => { let imageUrl = getImageUrl({ url: item?.largeImageUrl || null }); @@ -332,7 +334,7 @@ const normalizeAlbumArtist = ( const normalizePlaylist = ( item: z.infer, - server: ServerListItem | null, + server: null | ServerListItem, imageSize?: number, ): Playlist => { const imageUrl = getCoverArtUrl({ diff --git a/src/renderer/api/navidrome/navidrome-types.ts b/src/renderer/api/navidrome/navidrome-types.ts index 253aa9a8..125f1263 100644 --- a/src/renderer/api/navidrome/navidrome-types.ts +++ b/src/renderer/api/navidrome/navidrome-types.ts @@ -1,4 +1,5 @@ import { z } from 'zod'; + import { NDAlbumArtistListSort, NDAlbumListSort, diff --git a/src/renderer/api/query-keys.ts b/src/renderer/api/query-keys.ts index db453566..1c071e3a 100644 --- a/src/renderer/api/query-keys.ts +++ b/src/renderer/api/query-keys.ts @@ -1,28 +1,30 @@ import { QueryFunctionContext } from '@tanstack/react-query'; -import { LyricSource } from './types'; + import type { - AlbumListQuery, - SongListQuery, - AlbumDetailQuery, - AlbumArtistListQuery, - ArtistListQuery, - PlaylistListQuery, - PlaylistDetailQuery, - PlaylistSongListQuery, - UserListQuery, AlbumArtistDetailQuery, - TopSongListQuery, - SearchQuery, - SongDetailQuery, - RandomSongListQuery, - LyricsQuery, - LyricSearchQuery, + AlbumArtistListQuery, + AlbumDetailQuery, + AlbumListQuery, + ArtistListQuery, GenreListQuery, + LyricSearchQuery, + LyricsQuery, + PlaylistDetailQuery, + PlaylistListQuery, + PlaylistSongListQuery, + RandomSongListQuery, + SearchQuery, SimilarSongsQuery, + SongDetailQuery, + SongListQuery, + TopSongListQuery, + UserListQuery, } from './types'; +import { LyricSource } from './types'; + export const splitPaginatedQuery = (key: any) => { - const { startIndex, limit, ...filter } = key || {}; + const { limit, startIndex, ...filter } = key || {}; if (startIndex !== undefined || limit !== undefined) { return { @@ -51,7 +53,7 @@ export const queryKeys: Record< > = { albumArtists: { count: (serverId: string, query?: AlbumArtistListQuery) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && pagination) { return [serverId, 'albumArtists', 'count', filter, pagination] as const; @@ -68,7 +70,7 @@ export const queryKeys: Record< return [serverId, 'albumArtists', 'detail'] as const; }, list: (serverId: string, query?: AlbumArtistListQuery) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && pagination) { return [serverId, 'albumArtists', 'list', filter, pagination] as const; } @@ -87,7 +89,7 @@ export const queryKeys: Record< }, albums: { count: (serverId: string, query?: AlbumListQuery, artistId?: string) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && pagination && artistId) { return [serverId, 'albums', 'count', artistId, filter, pagination] as const; @@ -110,7 +112,7 @@ export const queryKeys: Record< detail: (serverId: string, query?: AlbumDetailQuery) => [serverId, 'albums', 'detail', query] as const, list: (serverId: string, query?: AlbumListQuery, artistId?: string) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && pagination && artistId) { return [serverId, 'albums', 'list', artistId, filter, pagination] as const; @@ -144,7 +146,7 @@ export const queryKeys: Record< }, artists: { list: (serverId: string, query?: ArtistListQuery) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && pagination) { return [serverId, 'artists', 'list', filter, pagination] as const; } @@ -159,7 +161,7 @@ export const queryKeys: Record< }, genres: { list: (serverId: string, query?: GenreListQuery) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && pagination) { return [serverId, 'genres', 'list', filter, pagination] as const; } @@ -177,7 +179,7 @@ export const queryKeys: Record< }, playlists: { detail: (serverId: string, id?: string, query?: PlaylistDetailQuery) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && pagination) { return [serverId, 'playlists', id, 'detail', filter, pagination] as const; } @@ -190,7 +192,7 @@ export const queryKeys: Record< return [serverId, 'playlists', 'detail'] as const; }, detailSongList: (serverId: string, id: string, query?: PlaylistSongListQuery) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && id && pagination) { return [serverId, 'playlists', id, 'detailSongList', filter, pagination] as const; @@ -205,7 +207,7 @@ export const queryKeys: Record< return [serverId, 'playlists', 'detailSongList'] as const; }, list: (serverId: string, query?: PlaylistListQuery) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && pagination) { return [serverId, 'playlists', 'list', filter, pagination] as const; } @@ -218,7 +220,7 @@ export const queryKeys: Record< }, root: (serverId: string) => [serverId, 'playlists'] as const, songList: (serverId: string, id?: string, query?: PlaylistSongListQuery) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && id && pagination) { return [serverId, 'playlists', id, 'songList', filter, pagination] as const; } @@ -246,7 +248,7 @@ export const queryKeys: Record< }, songs: { count: (serverId: string, query?: SongListQuery) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && pagination) { return [serverId, 'songs', 'count', filter, pagination] as const; } @@ -262,7 +264,7 @@ export const queryKeys: Record< return [serverId, 'songs', 'detail'] as const; }, list: (serverId: string, query?: SongListQuery) => { - const { pagination, filter } = splitPaginatedQuery(query); + const { filter, pagination } = splitPaginatedQuery(query); if (query && pagination) { return [serverId, 'songs', 'list', filter, pagination] as const; } diff --git a/src/renderer/api/subsonic.types.ts b/src/renderer/api/subsonic.types.ts index 89d103f3..803450df 100644 --- a/src/renderer/api/subsonic.types.ts +++ b/src/renderer/api/subsonic.types.ts @@ -1,32 +1,13 @@ -export type SSBaseResponse = { - serverVersion?: 'string'; - status: 'string'; - type?: 'string'; - version: 'string'; +export type SSAlbum = SSAlbumListEntry & { + song: SSSong[]; }; -export type SSMusicFolderList = SSMusicFolder[]; - -export type SSMusicFolderListResponse = { - musicFolders: { - musicFolder: SSMusicFolder[]; - }; -}; - -export type SSGenreList = SSGenre[]; - -export type SSGenreListResponse = { - genres: { - genre: SSGenre[]; - }; -}; +export type SSAlbumArtistDetail = SSAlbumArtistListEntry & { album: SSAlbumListEntry[] }; export type SSAlbumArtistDetailParams = { id: string; }; -export type SSAlbumArtistDetail = SSAlbumArtistListEntry & { album: SSAlbumListEntry[] }; - export type SSAlbumArtistDetailResponse = { artist: SSAlbumArtistListEntry & { album: SSAlbumListEntry[]; @@ -36,7 +17,19 @@ export type SSAlbumArtistDetailResponse = { export type SSAlbumArtistList = { items: SSAlbumArtistListEntry[]; startIndex: number; - totalRecordCount: number | null; + totalRecordCount: null | number; +}; + +export type SSAlbumArtistListEntry = { + albumCount: string; + artistImageUrl?: string; + coverArt?: string; + id: string; + name: string; +}; + +export type SSAlbumArtistListParams = { + musicFolderId?: string; }; export type SSAlbumArtistListResponse = { @@ -47,72 +40,16 @@ export type SSAlbumArtistListResponse = { }; }; -export type SSAlbumList = { - items: SSAlbumListEntry[]; - startIndex: number; - totalRecordCount: number | null; -}; - -export type SSAlbumListResponse = { - albumList2: { - album: SSAlbumListEntry[]; - }; -}; - export type SSAlbumDetail = Omit & { songs: SSSong[] }; export type SSAlbumDetailResponse = { album: SSAlbum; }; -export type SSArtistInfoParams = { - count?: number; - id: string; - includeNotPresent?: boolean; -}; - -export type SSArtistInfoResponse = { - artistInfo2: SSArtistInfo; -}; - -export type SSArtistInfo = { - biography: string; - largeImageUrl?: string; - lastFmUrl?: string; - mediumImageUrl?: string; - musicBrainzId?: string; - similarArtist?: { - albumCount: string; - artistImageUrl?: string; - coverArt?: string; - id: string; - name: string; - }[]; - smallImageUrl?: string; -}; - -export type SSMusicFolder = { - id: number; - name: string; -}; - -export type SSGenre = { - albumCount?: number; - songCount?: number; - value: string; -}; - -export type SSArtistIndex = { - artist: SSAlbumArtistListEntry[]; - name: string; -}; - -export type SSAlbumArtistListEntry = { - albumCount: string; - artistImageUrl?: string; - coverArt?: string; - id: string; - name: string; +export type SSAlbumList = { + items: SSAlbumListEntry[]; + startIndex: number; + totalRecordCount: null | number; }; export type SSAlbumListEntry = { @@ -135,9 +72,111 @@ export type SSAlbumListEntry = { year: number; }; -export type SSAlbum = { - song: SSSong[]; -} & SSAlbumListEntry; +export type SSAlbumListParams = { + fromYear?: number; + genre?: string; + musicFolderId?: string; + offset?: number; + size?: number; + toYear?: number; + type: string; +}; + +export type SSAlbumListResponse = { + albumList2: { + album: SSAlbumListEntry[]; + }; +}; + +export type SSArtistIndex = { + artist: SSAlbumArtistListEntry[]; + name: string; +}; + +export type SSArtistInfo = { + biography: string; + largeImageUrl?: string; + lastFmUrl?: string; + mediumImageUrl?: string; + musicBrainzId?: string; + similarArtist?: { + albumCount: string; + artistImageUrl?: string; + coverArt?: string; + id: string; + name: string; + }[]; + smallImageUrl?: string; +}; + +export type SSArtistInfoParams = { + count?: number; + id: string; + includeNotPresent?: boolean; +}; + +export type SSArtistInfoResponse = { + artistInfo2: SSArtistInfo; +}; + +export type SSBaseResponse = { + serverVersion?: 'string'; + status: 'string'; + type?: 'string'; + version: 'string'; +}; + +export type SSFavorite = null; + +export type SSFavoriteParams = { + albumId?: string; + artistId?: string; + id?: string; +}; + +export type SSFavoriteResponse = null; + +export type SSGenre = { + albumCount?: number; + songCount?: number; + value: string; +}; + +export type SSGenreList = SSGenre[]; + +export type SSGenreListResponse = { + genres: { + genre: SSGenre[]; + }; +}; + +export type SSMusicFolder = { + id: number; + name: string; +}; + +export type SSMusicFolderList = SSMusicFolder[]; + +export type SSMusicFolderListResponse = { + musicFolders: { + musicFolder: SSMusicFolder[]; + }; +}; + +export type SSRating = null; + +export type SSRatingParams = { + id: string; + rating: number; +}; + +export type SSRatingResponse = null; + +export type SSScrobbleParams = { + id: string; + submission?: boolean; + time?: number; +}; export type SSSong = { album: string; @@ -167,39 +206,12 @@ export type SSSong = { year: number; }; -export type SSAlbumListParams = { - fromYear?: number; - genre?: string; - musicFolderId?: string; - offset?: number; - size?: number; - toYear?: number; - type: string; +export type SSTopSongList = { + items: SSSong[]; + startIndex: number; + totalRecordCount: null | number; }; -export type SSAlbumArtistListParams = { - musicFolderId?: string; -}; - -export type SSFavoriteParams = { - albumId?: string; - artistId?: string; - id?: string; -}; - -export type SSFavorite = null; - -export type SSFavoriteResponse = null; - -export type SSRatingParams = { - id: string; - rating: number; -}; - -export type SSRating = null; - -export type SSRatingResponse = null; - export type SSTopSongListParams = { artist: string; count?: number; @@ -210,15 +222,3 @@ export type SSTopSongListResponse = { song: SSSong[]; }; }; - -export type SSTopSongList = { - items: SSSong[]; - startIndex: number; - totalRecordCount: number | null; -}; - -export type SSScrobbleParams = { - id: string; - submission?: boolean; - time?: number; -}; diff --git a/src/renderer/api/subsonic/subsonic-api.ts b/src/renderer/api/subsonic/subsonic-api.ts index 23c919d1..f11d5734 100644 --- a/src/renderer/api/subsonic/subsonic-api.ts +++ b/src/renderer/api/subsonic/subsonic-api.ts @@ -1,12 +1,13 @@ import { initClient, initContract } from '@ts-rest/core'; -import axios, { Method, AxiosError, isAxiosError, AxiosResponse } from 'axios'; +import axios, { AxiosError, AxiosResponse, isAxiosError, Method } from 'axios'; import omitBy from 'lodash/omitBy'; import qs from 'qs'; import { z } from 'zod'; + +import i18n from '/@/i18n/i18n'; import { ssType } from '/@/renderer/api/subsonic/subsonic-types'; import { ServerListItem } from '/@/renderer/api/types'; import { toast } from '/@/renderer/components/toast/index'; -import i18n from '/@/i18n/i18n'; const c = initContract(); @@ -284,15 +285,15 @@ const silentlyTransformResponse = (data: any) => { }; export const ssApiClient = (args: { - server: ServerListItem | null; + server: null | ServerListItem; signal?: AbortSignal; silent?: boolean; url?: string; }) => { - const { server, url, signal, silent } = args; + const { server, signal, silent, url } = args; return initClient(contract, { - api: async ({ path, method, headers, body }) => { + api: async ({ body, headers, method, path }) => { let baseUrl: string | undefined; const authParams: Record = {}; @@ -339,7 +340,7 @@ export const ssApiClient = (args: { headers: result.headers as any, status: result.status, }; - } catch (e: Error | AxiosError | any) { + } catch (e: any | AxiosError | Error) { if (isAxiosError(e)) { if (e.code === 'ERR_NETWORK') { throw new Error( diff --git a/src/renderer/api/subsonic/subsonic-controller.ts b/src/renderer/api/subsonic/subsonic-controller.ts index b63698b8..6bea97f8 100644 --- a/src/renderer/api/subsonic/subsonic-controller.ts +++ b/src/renderer/api/subsonic/subsonic-controller.ts @@ -2,44 +2,45 @@ import dayjs from 'dayjs'; import filter from 'lodash/filter'; import orderBy from 'lodash/orderBy'; import md5 from 'md5'; + +import { ServerFeatures } from '/@/renderer/api/features-types'; import { ssApiClient } from '/@/renderer/api/subsonic/subsonic-api'; import { ssNormalize } from '/@/renderer/api/subsonic/subsonic-normalize'; import { AlbumListSortType, SubsonicExtensions } from '/@/renderer/api/subsonic/subsonic-types'; import { - LibraryItem, - Song, - ControllerEndpoint, - sortSongList, - sortAlbumArtistList, - PlaylistListSort, - GenreListSort, AlbumListSort, + ControllerEndpoint, + GenreListSort, + LibraryItem, + PlaylistListSort, + Song, + sortAlbumArtistList, sortAlbumList, SortOrder, + sortSongList, } from '/@/renderer/api/types'; import { randomString } from '/@/renderer/utils'; -import { ServerFeatures } from '/@/renderer/api/features-types'; const ALBUM_LIST_SORT_MAPPING: Record = { - [AlbumListSort.RANDOM]: AlbumListSortType.RANDOM, [AlbumListSort.ALBUM_ARTIST]: AlbumListSortType.ALPHABETICAL_BY_ARTIST, - [AlbumListSort.PLAY_COUNT]: AlbumListSortType.FREQUENT, - [AlbumListSort.RECENTLY_ADDED]: AlbumListSortType.NEWEST, - [AlbumListSort.FAVORITED]: AlbumListSortType.STARRED, - [AlbumListSort.YEAR]: AlbumListSortType.BY_YEAR, - [AlbumListSort.NAME]: AlbumListSortType.ALPHABETICAL_BY_NAME, - [AlbumListSort.COMMUNITY_RATING]: undefined, - [AlbumListSort.DURATION]: undefined, - [AlbumListSort.CRITIC_RATING]: undefined, - [AlbumListSort.RATING]: undefined, [AlbumListSort.ARTIST]: undefined, + [AlbumListSort.COMMUNITY_RATING]: undefined, + [AlbumListSort.CRITIC_RATING]: undefined, + [AlbumListSort.DURATION]: undefined, + [AlbumListSort.FAVORITED]: AlbumListSortType.STARRED, + [AlbumListSort.NAME]: AlbumListSortType.ALPHABETICAL_BY_NAME, + [AlbumListSort.PLAY_COUNT]: AlbumListSortType.FREQUENT, + [AlbumListSort.RANDOM]: AlbumListSortType.RANDOM, + [AlbumListSort.RATING]: undefined, + [AlbumListSort.RECENTLY_ADDED]: AlbumListSortType.NEWEST, [AlbumListSort.RECENTLY_PLAYED]: AlbumListSortType.RECENT, [AlbumListSort.RELEASE_DATE]: undefined, [AlbumListSort.SONG_COUNT]: undefined, + [AlbumListSort.YEAR]: AlbumListSortType.BY_YEAR, }; export const SubsonicController: ControllerEndpoint = { - addToPlaylist: async ({ body, query, apiClientProps }) => { + addToPlaylist: async ({ apiClientProps, body, query }) => { const res = await ssApiClient(apiClientProps).updatePlaylist({ query: { playlistId: query.id, @@ -98,7 +99,7 @@ export const SubsonicController: ControllerEndpoint = { }; }, createFavorite: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).createFavorite({ query: { @@ -114,7 +115,7 @@ export const SubsonicController: ControllerEndpoint = { return null; }, - createPlaylist: async ({ body, apiClientProps }) => { + createPlaylist: async ({ apiClientProps, body }) => { const res = await ssApiClient(apiClientProps).createPlaylist({ query: { name: body.name, @@ -131,7 +132,7 @@ export const SubsonicController: ControllerEndpoint = { }; }, deleteFavorite: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).removeFavorite({ query: { @@ -148,7 +149,7 @@ export const SubsonicController: ControllerEndpoint = { return null; }, deletePlaylist: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).deletePlaylist({ query: { @@ -163,7 +164,7 @@ export const SubsonicController: ControllerEndpoint = { return null; }, getAlbumArtistDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const artistInfoRes = await ssApiClient(apiClientProps).getArtistInfo({ query: { @@ -198,7 +199,7 @@ export const SubsonicController: ControllerEndpoint = { }; }, getAlbumArtistList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).getArtists({ query: { @@ -237,7 +238,7 @@ export const SubsonicController: ControllerEndpoint = { getAlbumArtistListCount: (args) => SubsonicController.getAlbumArtistList(args).then((res) => res!.totalRecordCount!), getAlbumDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).getAlbum({ query: { @@ -252,7 +253,7 @@ export const SubsonicController: ControllerEndpoint = { return ssNormalize.album(res.body.album, apiClientProps.server); }, getAlbumList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (query.searchTerm) { const res = await ssApiClient(apiClientProps).search3({ @@ -398,7 +399,7 @@ export const SubsonicController: ControllerEndpoint = { }; }, getAlbumListCount: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; if (query.searchTerm) { let fetchNextPage = true; @@ -516,7 +517,7 @@ export const SubsonicController: ControllerEndpoint = { return totalRecordCount; }, getArtistList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).getArtists({ query: { @@ -570,7 +571,7 @@ export const SubsonicController: ControllerEndpoint = { '&c=Feishin' ); }, - getGenreList: async ({ query, apiClientProps }) => { + getGenreList: async ({ apiClientProps, query }) => { const sortOrder = query.sortOrder.toLowerCase() as 'asc' | 'desc'; const res = await ssApiClient(apiClientProps).getGenres({}); @@ -624,7 +625,7 @@ export const SubsonicController: ControllerEndpoint = { }; }, getPlaylistDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).getPlaylist({ query: { @@ -638,7 +639,7 @@ export const SubsonicController: ControllerEndpoint = { return ssNormalize.playlist(res.body.playlist, apiClientProps.server); }, - getPlaylistList: async ({ query, apiClientProps }) => { + getPlaylistList: async ({ apiClientProps, query }) => { const sortOrder = query.sortOrder.toLowerCase() as 'asc' | 'desc'; const res = await ssApiClient(apiClientProps).getPlaylists({}); @@ -686,7 +687,7 @@ export const SubsonicController: ControllerEndpoint = { totalRecordCount: results.length, }; }, - getPlaylistListCount: async ({ query, apiClientProps }) => { + getPlaylistListCount: async ({ apiClientProps, query }) => { const res = await ssApiClient(apiClientProps).getPlaylists({}); if (res.status !== 200) { @@ -705,7 +706,7 @@ export const SubsonicController: ControllerEndpoint = { return results.length; }, - getPlaylistSongList: async ({ query, apiClientProps }) => { + getPlaylistSongList: async ({ apiClientProps, query }) => { const res = await ssApiClient(apiClientProps).getPlaylist({ query: { id: query.id, @@ -731,7 +732,7 @@ export const SubsonicController: ControllerEndpoint = { }; }, getRandomSongList: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).getRandomSongList({ query: { @@ -842,7 +843,7 @@ export const SubsonicController: ControllerEndpoint = { }, []); }, getSongDetail: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).getSong({ query: { @@ -856,7 +857,7 @@ export const SubsonicController: ControllerEndpoint = { return ssNormalize.song(res.body.song, apiClientProps.server); }, - getSongList: async ({ query, apiClientProps }) => { + getSongList: async ({ apiClientProps, query }) => { const fromAlbumPromises = []; const artistDetailPromises = []; let results: any[] = []; @@ -1028,7 +1029,7 @@ export const SubsonicController: ControllerEndpoint = { }; }, getSongListCount: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; let fetchNextPage = true; let startIndex = 0; @@ -1196,7 +1197,7 @@ export const SubsonicController: ControllerEndpoint = { return totalRecordCount; }, getStructuredLyrics: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).getStructuredLyrics({ query: { @@ -1238,7 +1239,7 @@ export const SubsonicController: ControllerEndpoint = { }); }, getTopSongs: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).getTopSongsList({ query: { @@ -1261,7 +1262,7 @@ export const SubsonicController: ControllerEndpoint = { }; }, getTranscodingUrl: (args) => { - const { base, format, bitrate } = args.query; + const { base, bitrate, format } = args.query; let url = base; if (format) { url += `&format=${format}`; @@ -1272,7 +1273,7 @@ export const SubsonicController: ControllerEndpoint = { return url; }, - removeFromPlaylist: async ({ query, apiClientProps }) => { + removeFromPlaylist: async ({ apiClientProps, query }) => { const res = await ssApiClient(apiClientProps).updatePlaylist({ query: { playlistId: query.id, @@ -1287,7 +1288,7 @@ export const SubsonicController: ControllerEndpoint = { return null; }, scrobble: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).scrobble({ query: { @@ -1304,7 +1305,7 @@ export const SubsonicController: ControllerEndpoint = { }, search: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const res = await ssApiClient(apiClientProps).search3({ query: { @@ -1335,7 +1336,7 @@ export const SubsonicController: ControllerEndpoint = { }; }, setRating: async (args) => { - const { query, apiClientProps } = args; + const { apiClientProps, query } = args; const itemIds = query.item.map((item) => item.id); @@ -1351,7 +1352,7 @@ export const SubsonicController: ControllerEndpoint = { return null; }, updatePlaylist: async (args) => { - const { body, query, apiClientProps } = args; + const { apiClientProps, body, query } = args; const res = await ssApiClient(apiClientProps).updatePlaylist({ query: { diff --git a/src/renderer/api/subsonic/subsonic-normalize.ts b/src/renderer/api/subsonic/subsonic-normalize.ts index 7f0e2b56..beb98643 100644 --- a/src/renderer/api/subsonic/subsonic-normalize.ts +++ b/src/renderer/api/subsonic/subsonic-normalize.ts @@ -1,16 +1,17 @@ import { nanoid } from 'nanoid'; import { z } from 'zod'; + import { ssType } from '/@/renderer/api/subsonic/subsonic-types'; import { - QueueSong, - LibraryItem, - AlbumArtist, Album, + AlbumArtist, + Genre, + LibraryItem, + Playlist, + QueueSong, + RelatedArtist, ServerListItem, ServerType, - Playlist, - Genre, - RelatedArtist, } from '/@/renderer/api/types'; const getCoverArtUrl = (args: { @@ -37,9 +38,9 @@ const getCoverArtUrl = (args: { const getArtists = ( item: - | z.infer | z.infer - | z.infer, + | z.infer + | z.infer, ) => { const albumArtists: RelatedArtist[] = item.albumArtists ? item.albumArtists.map((item) => ({ @@ -69,7 +70,7 @@ const getArtists = ( }, ]; - let participants: Record | null = null; + let participants: null | Record = null; if (item.contributors) { participants = {}; @@ -98,9 +99,9 @@ const getArtists = ( const getGenres = ( item: - | z.infer | z.infer - | z.infer, + | z.infer + | z.infer, ): Genre[] => { return item.genres ? item.genres.map((genre) => ({ @@ -123,7 +124,7 @@ const getGenres = ( const normalizeSong = ( item: z.infer, - server: ServerListItem | null, + server: null | ServerListItem, size?: number, ): QueueSong => { const imageUrl = @@ -194,7 +195,7 @@ const normalizeAlbumArtist = ( item: | z.infer | z.infer, - server: ServerListItem | null, + server: null | ServerListItem, imageSize?: number, ): AlbumArtist => { const imageUrl = @@ -229,7 +230,7 @@ const normalizeAlbumArtist = ( const normalizeAlbum = ( item: z.infer | z.infer, - server: ServerListItem | null, + server: null | ServerListItem, imageSize?: number, ): Album => { const imageUrl = @@ -280,7 +281,7 @@ const normalizePlaylist = ( item: | z.infer | z.infer, - server: ServerListItem | null, + server: null | ServerListItem, ): Playlist => { return { description: item.comment || null, diff --git a/src/renderer/api/types.ts b/src/renderer/api/types.ts index a24abd9e..854721f2 100644 --- a/src/renderer/api/types.ts +++ b/src/renderer/api/types.ts @@ -2,28 +2,29 @@ import orderBy from 'lodash/orderBy'; import reverse from 'lodash/reverse'; import shuffle from 'lodash/shuffle'; import { z } from 'zod'; + import { ServerFeatures } from './features-types'; +import { + JFAlbumArtistListSort, + JFAlbumListSort, + JFArtistListSort, + JFGenreListSort, + JFPlaylistListSort, + JFSongListSort, + JFSortOrder, +} from './jellyfin.types'; import { jfType } from './jellyfin/jellyfin-types'; import { - JFSortOrder, - JFAlbumListSort, - JFSongListSort, - JFAlbumArtistListSort, - JFArtistListSort, - JFPlaylistListSort, - JFGenreListSort, -} from './jellyfin.types'; -import { ndType } from './navidrome/navidrome-types'; -import { - NDSortOrder, - NDOrder, - NDAlbumListSort, NDAlbumArtistListSort, + NDAlbumListSort, + NDGenreListSort, + NDOrder, NDPlaylistListSort, NDSongListSort, + NDSortOrder, NDUserListSort, - NDGenreListSort, } from './navidrome.types'; +import { ndType } from './navidrome/navidrome-types'; export enum LibraryItem { ALBUM = 'album', @@ -34,29 +35,29 @@ export enum LibraryItem { SONG = 'song', } -export type AnyLibraryItem = Album | AlbumArtist | Artist | Playlist | Song | QueueSong; - -export type AnyLibraryItems = - | Album[] - | AlbumArtist[] - | Artist[] - | Playlist[] - | Song[] - | QueueSong[]; +export enum ServerType { + JELLYFIN = 'jellyfin', + NAVIDROME = 'navidrome', + SUBSONIC = 'subsonic', +} export enum SortOrder { ASC = 'ASC', DESC = 'DESC', } -export type User = { - createdAt: string | null; - email: string | null; - id: string; - isAdmin: boolean | null; - lastLoginAt: string | null; - name: string; - updatedAt: string | null; +export type AnyLibraryItem = Album | AlbumArtist | Artist | Playlist | QueueSong | Song; + +export type AnyLibraryItems = + | Album[] + | AlbumArtist[] + | Artist[] + | Playlist[] + | QueueSong[] + | Song[]; + +export type QueueSong = Song & { + uniqueId: string; }; export type ServerListItem = { @@ -68,19 +69,19 @@ export type ServerListItem = { savePassword?: boolean; type: ServerType; url: string; - userId: string | null; + userId: null | string; username: string; version?: string; }; -export enum ServerType { - JELLYFIN = 'jellyfin', - NAVIDROME = 'navidrome', - SUBSONIC = 'subsonic', -} - -export type QueueSong = Song & { - uniqueId: string; +export type User = { + createdAt: null | string; + email: null | string; + id: string; + isAdmin: boolean | null; + lastLoginAt: null | string; + name: string; + updatedAt: null | string; }; type SortOrderMap = { @@ -116,6 +117,10 @@ export enum ExternalType { LINK = 'LINK', } +export enum GenreListSort { + NAME = 'name', +} + export enum ImageType { BACKDROP = 'BACKDROP', LOGO = 'LOGO', @@ -123,212 +128,112 @@ export enum ImageType { SCREENSHOT = 'SCREENSHOT', } -export type EndpointDetails = { - server: ServerListItem; -}; - -export interface BasePaginatedResponse { - error?: string | any; - items: T; - startIndex: number; - totalRecordCount: number | null; -} - -export type AuthenticationResponse = { - credential: string; - ndCredential?: string; - userId: string | null; - username: string; -}; - -export type Genre = { - albumCount?: number; - id: string; - imageUrl: string | null; - itemType: LibraryItem.GENRE; - name: string; - songCount?: number; -}; - export type Album = { albumArtist: string; albumArtists: RelatedArtist[]; artists: RelatedArtist[]; - backdropImageUrl: string | null; - comment: string | null; + backdropImageUrl: null | string; + comment: null | string; createdAt: string; - duration: number | null; + duration: null | number; genres: Genre[]; id: string; - imagePlaceholderUrl: string | null; - imageUrl: string | null; + imagePlaceholderUrl: null | string; + imageUrl: null | string; isCompilation: boolean | null; itemType: LibraryItem.ALBUM; - lastPlayedAt: string | null; - mbzId: string | null; + lastPlayedAt: null | string; + mbzId: null | string; name: string; - originalDate: string | null; - participants: Record | null; - playCount: number | null; - releaseDate: string | null; - releaseYear: number | null; + originalDate: null | string; + participants: null | Record; + playCount: null | number; + releaseDate: null | string; + releaseYear: null | number; serverId: string; serverType: ServerType; - size: number | null; - songCount: number | null; + size: null | number; + songCount: null | number; songs?: Song[]; - tags: Record | null; + tags: null | Record; uniqueId: string; updatedAt: string; userFavorite: boolean; - userRating: number | null; + userRating: null | number; } & { songs?: Song[] }; -export type GainInfo = { - album?: number; - track?: number; -}; - -export type Song = { - album: string | null; - albumArtists: RelatedArtist[]; - albumId: string; - artistName: string; - artists: RelatedArtist[]; - bitRate: number; - bpm: number | null; - channels: number | null; - comment: string | null; - compilation: boolean | null; - container: string | null; - createdAt: string; - discNumber: number; - discSubtitle: string | null; - duration: number; - gain: GainInfo | null; - genres: Genre[]; - id: string; - imagePlaceholderUrl: string | null; - imageUrl: string | null; - itemType: LibraryItem.SONG; - lastPlayedAt: string | null; - lyrics: string | null; - name: string; - participants: Record | null; - path: string | null; - peak: GainInfo | null; - playCount: number; - playlistItemId?: string; - releaseDate: string | null; - releaseYear: string | null; - serverId: string; - serverType: ServerType; - size: number; - streamUrl: string; - tags: Record | null; - trackNumber: number; - uniqueId: string; - updatedAt: string; - userFavorite: boolean; - userRating: number | null; -}; - export type AlbumArtist = { - albumCount: number | null; - backgroundImageUrl: string | null; - biography: string | null; - duration: number | null; + albumCount: null | number; + backgroundImageUrl: null | string; + biography: null | string; + duration: null | number; genres: Genre[]; id: string; - imageUrl: string | null; + imageUrl: null | string; itemType: LibraryItem.ALBUM_ARTIST; - lastPlayedAt: string | null; - mbz: string | null; + lastPlayedAt: null | string; + mbz: null | string; name: string; - playCount: number | null; + playCount: null | number; serverId: string; serverType: ServerType; - similarArtists: RelatedArtist[] | null; - songCount: number | null; + similarArtists: null | RelatedArtist[]; + songCount: null | number; userFavorite: boolean; - userRating: number | null; -}; - -export type RelatedAlbumArtist = { - id: string; - name: string; + userRating: null | number; }; export type Artist = { - biography: string | null; + biography: null | string; createdAt: string; id: string; itemType: LibraryItem.ARTIST; name: string; - remoteCreatedAt: string | null; + remoteCreatedAt: null | string; serverFolderId: string; serverId: string; serverType: ServerType; updatedAt: string; }; -export type RelatedArtist = { - id: string; - imageUrl: string | null; - name: string; +export type AuthenticationResponse = { + credential: string; + ndCredential?: string; + userId: null | string; + username: string; }; -export type MusicFolder = { - id: string; - name: string; -}; - -export type Playlist = { - description: string | null; - duration: number | null; - genres: Genre[]; - id: string; - imagePlaceholderUrl: string | null; - imageUrl: string | null; - itemType: LibraryItem.PLAYLIST; - name: string; - owner: string | null; - ownerId: string | null; - public: boolean | null; - rules?: Record | null; - serverId: string; - serverType: ServerType; - size: number | null; - songCount: number | null; - sync?: boolean | null; -}; - -export type GenresResponse = Genre[]; - -export type MusicFoldersResponse = MusicFolder[]; - -export type ListSortOrder = NDOrder | JFSortOrder; - -type BaseEndpointArgs = { - apiClientProps: { - server: ServerListItem | null; - signal?: AbortSignal; - }; -}; +export interface BasePaginatedResponse { + error?: any | string; + items: T; + startIndex: number; + totalRecordCount: null | number; +} export interface BaseQuery { sortBy: T; sortOrder: SortOrder; } -// Genre List -export type GenreListResponse = BasePaginatedResponse | null | undefined; +export type EndpointDetails = { + server: ServerListItem; +}; -export type GenreListArgs = { query: GenreListQuery } & BaseEndpointArgs; +export type GainInfo = { + album?: number; + track?: number; +}; -export enum GenreListSort { - NAME = 'name', -} +export type Genre = { + albumCount?: number; + id: string; + imageUrl: null | string; + itemType: LibraryItem.GENRE; + name: string; + songCount?: number; +}; + +export type GenreListArgs = BaseEndpointArgs & { query: GenreListQuery }; export interface GenreListQuery extends BaseQuery { _custom?: { @@ -341,6 +246,102 @@ export interface GenreListQuery extends BaseQuery { startIndex: number; } +// Genre List +export type GenreListResponse = BasePaginatedResponse | null | undefined; + +export type GenresResponse = Genre[]; + +export type ListSortOrder = JFSortOrder | NDOrder; + +export type MusicFolder = { + id: string; + name: string; +}; + +export type MusicFoldersResponse = MusicFolder[]; + +export type Playlist = { + description: null | string; + duration: null | number; + genres: Genre[]; + id: string; + imagePlaceholderUrl: null | string; + imageUrl: null | string; + itemType: LibraryItem.PLAYLIST; + name: string; + owner: null | string; + ownerId: null | string; + public: boolean | null; + rules?: null | Record; + serverId: string; + serverType: ServerType; + size: null | number; + songCount: null | number; + sync?: boolean | null; +}; + +export type RelatedAlbumArtist = { + id: string; + name: string; +}; + +export type RelatedArtist = { + id: string; + imageUrl: null | string; + name: string; +}; + +export type Song = { + album: null | string; + albumArtists: RelatedArtist[]; + albumId: string; + artistName: string; + artists: RelatedArtist[]; + bitRate: number; + bpm: null | number; + channels: null | number; + comment: null | string; + compilation: boolean | null; + container: null | string; + createdAt: string; + discNumber: number; + discSubtitle: null | string; + duration: number; + gain: GainInfo | null; + genres: Genre[]; + id: string; + imagePlaceholderUrl: null | string; + imageUrl: null | string; + itemType: LibraryItem.SONG; + lastPlayedAt: null | string; + lyrics: null | string; + name: string; + participants: null | Record; + path: null | string; + peak: GainInfo | null; + playCount: number; + playlistItemId?: string; + releaseDate: null | string; + releaseYear: null | string; + serverId: string; + serverType: ServerType; + size: number; + streamUrl: string; + tags: null | Record; + trackNumber: number; + uniqueId: string; + updatedAt: string; + userFavorite: boolean; + userRating: null | number; +}; + +type BaseEndpointArgs = { + apiClientProps: { + server: null | ServerListItem; + signal?: AbortSignal; + }; +}; + type GenreListSortMap = { jellyfin: Record; navidrome: Record; @@ -359,9 +360,6 @@ export const genreListSortMap: GenreListSortMap = { }, }; -// Album List -export type AlbumListResponse = BasePaginatedResponse | null | undefined; - export enum AlbumListSort { ALBUM_ARTIST = 'albumArtist', ARTIST = 'artist', @@ -380,6 +378,8 @@ export enum AlbumListSort { YEAR = 'year', } +export type AlbumListArgs = BaseEndpointArgs & { query: AlbumListQuery }; + export interface AlbumListQuery extends BaseQuery { _custom?: { jellyfin?: Partial>; @@ -397,7 +397,8 @@ export interface AlbumListQuery extends BaseQuery { startIndex: number; } -export type AlbumListArgs = { query: AlbumListQuery } & BaseEndpointArgs; +// Album List +export type AlbumListResponse = BasePaginatedResponse | null | undefined; type AlbumListSortMap = { jellyfin: Record; @@ -460,21 +461,6 @@ export const albumListSortMap: AlbumListSortMap = { }, }; -// Album Detail -export type AlbumDetailResponse = Album | null | undefined; - -export type AlbumDetailQuery = { id: string }; - -export type AlbumDetailArgs = { query: AlbumDetailQuery } & BaseEndpointArgs; - -export type AlbumInfo = { - imageUrl: string | null; - notes: string | null; -}; - -// Song List -export type SongListResponse = BasePaginatedResponse | null | undefined; - export enum SongListSort { ALBUM = 'album', ALBUM_ARTIST = 'albumArtist', @@ -496,6 +482,20 @@ export enum SongListSort { YEAR = 'year', } +export type AlbumDetailArgs = BaseEndpointArgs & { query: AlbumDetailQuery }; + +export type AlbumDetailQuery = { id: string }; + +// Album Detail +export type AlbumDetailResponse = Album | null | undefined; + +export type AlbumInfo = { + imageUrl: null | string; + notes: null | string; +}; + +export type SongListArgs = BaseEndpointArgs & { query: SongListQuery }; + export interface SongListQuery extends BaseQuery { _custom?: { jellyfin?: Partial>; @@ -516,7 +516,8 @@ export interface SongListQuery extends BaseQuery { startIndex: number; } -export type SongListArgs = { query: SongListQuery } & BaseEndpointArgs; +// Song List +export type SongListResponse = BasePaginatedResponse | null | undefined; type SongListSortMap = { jellyfin: Record; @@ -587,16 +588,6 @@ export const songListSortMap: SongListSortMap = { }, }; -// Song Detail -export type SongDetailResponse = Song | null | undefined; - -export type SongDetailQuery = { id: string }; - -export type SongDetailArgs = { query: SongDetailQuery } & BaseEndpointArgs; - -// Album Artist List -export type AlbumArtistListResponse = BasePaginatedResponse | null | undefined; - export enum AlbumArtistListSort { ALBUM = 'album', ALBUM_COUNT = 'albumCount', @@ -611,6 +602,8 @@ export enum AlbumArtistListSort { SONG_COUNT = 'songCount', } +export type AlbumArtistListArgs = BaseEndpointArgs & { query: AlbumArtistListQuery }; + export interface AlbumArtistListQuery extends BaseQuery { _custom?: { jellyfin?: Partial>; @@ -622,7 +615,15 @@ export interface AlbumArtistListQuery extends BaseQuery { startIndex: number; } -export type AlbumArtistListArgs = { query: AlbumArtistListQuery } & BaseEndpointArgs; +// Album Artist List +export type AlbumArtistListResponse = BasePaginatedResponse | null | undefined; + +export type SongDetailArgs = BaseEndpointArgs & { query: SongDetailQuery }; + +export type SongDetailQuery = { id: string }; + +// Song Detail +export type SongDetailResponse = null | Song | undefined; type AlbumArtistListSortMap = { jellyfin: Record; @@ -674,15 +675,6 @@ export const albumArtistListSortMap: AlbumArtistListSortMap = { // Album Artist Detail -export type AlbumArtistDetailResponse = AlbumArtist | null; - -export type AlbumArtistDetailQuery = { id: string }; - -export type AlbumArtistDetailArgs = { query: AlbumArtistDetailQuery } & BaseEndpointArgs; - -// Artist List -export type ArtistListResponse = BasePaginatedResponse | null | undefined; - export enum ArtistListSort { ALBUM = 'album', ALBUM_COUNT = 'albumCount', @@ -697,6 +689,14 @@ export enum ArtistListSort { SONG_COUNT = 'songCount', } +export type AlbumArtistDetailArgs = BaseEndpointArgs & { query: AlbumArtistDetailQuery }; + +export type AlbumArtistDetailQuery = { id: string }; + +export type AlbumArtistDetailResponse = AlbumArtist | null; + +export type ArtistListArgs = BaseEndpointArgs & { query: ArtistListQuery }; + export interface ArtistListQuery extends BaseQuery { _custom?: { jellyfin?: Partial>; @@ -709,7 +709,8 @@ export interface ArtistListQuery extends BaseQuery { startIndex: number; } -export type ArtistListArgs = { query: ArtistListQuery } & BaseEndpointArgs; +// Artist List +export type ArtistListResponse = BasePaginatedResponse | null | undefined; type ArtistListSortMap = { jellyfin: Record; @@ -761,71 +762,33 @@ export const artistListSortMap: ArtistListSortMap = { // Artist Detail -// Favorite -export type FavoriteResponse = null | undefined; +export enum PlaylistListSort { + DURATION = 'duration', + NAME = 'name', + OWNER = 'owner', + PUBLIC = 'public', + SONG_COUNT = 'songCount', + UPDATED_AT = 'updatedAt', +} -export type FavoriteQuery = { - id: string[]; - type: LibraryItem; -}; - -export type FavoriteArgs = { query: FavoriteQuery; serverId?: string } & BaseEndpointArgs; - -// Rating -export type RatingResponse = null | undefined; - -export type RatingQuery = { - item: AnyLibraryItems; - rating: number; -}; - -export type SetRatingArgs = { query: RatingQuery; serverId?: string } & BaseEndpointArgs; - -// Sharing -export type ShareItemResponse = { id: string } | undefined; - -export type ShareItemBody = { - description: string; - downloadable: boolean; - expires: number; - resourceIds: string; - resourceType: string; -}; - -export type ShareItemArgs = { body: ShareItemBody; serverId?: string } & BaseEndpointArgs; - -// Add to playlist -export type AddToPlaylistResponse = null | undefined; - -export type AddToPlaylistQuery = { - id: string; +export type AddToPlaylistArgs = BaseEndpointArgs & { + body: AddToPlaylistBody; + query: AddToPlaylistQuery; + serverId?: string; }; export type AddToPlaylistBody = { songId: string[]; }; -export type AddToPlaylistArgs = { - body: AddToPlaylistBody; - query: AddToPlaylistQuery; - serverId?: string; -} & BaseEndpointArgs; - -// Remove from playlist -export type RemoveFromPlaylistResponse = null | undefined; - -export type RemoveFromPlaylistQuery = { +export type AddToPlaylistQuery = { id: string; - songId: string[]; }; -export type RemoveFromPlaylistArgs = { - query: RemoveFromPlaylistQuery; - serverId?: string; -} & BaseEndpointArgs; +// Add to playlist +export type AddToPlaylistResponse = null | undefined; -// Create Playlist -export type CreatePlaylistResponse = { id: string } | undefined; +export type CreatePlaylistArgs = BaseEndpointArgs & { body: CreatePlaylistBody; serverId?: string }; export type CreatePlaylistBody = { _custom?: { @@ -841,13 +804,84 @@ export type CreatePlaylistBody = { public?: boolean; }; -export type CreatePlaylistArgs = { body: CreatePlaylistBody; serverId?: string } & BaseEndpointArgs; +// Create Playlist +export type CreatePlaylistResponse = undefined | { id: string }; -// Update Playlist -export type UpdatePlaylistResponse = null | undefined; +export type DeletePlaylistArgs = BaseEndpointArgs & { + query: DeletePlaylistQuery; + serverId?: string; +}; -export type UpdatePlaylistQuery = { +export type DeletePlaylistQuery = { id: string }; + +// Delete Playlist +export type DeletePlaylistResponse = null | undefined; + +export type FavoriteArgs = BaseEndpointArgs & { query: FavoriteQuery; serverId?: string }; + +export type FavoriteQuery = { + id: string[]; + type: LibraryItem; +}; + +// Favorite +export type FavoriteResponse = null | undefined; + +export type PlaylistListArgs = BaseEndpointArgs & { query: PlaylistListQuery }; + +export interface PlaylistListQuery extends BaseQuery { + _custom?: { + jellyfin?: Partial>; + navidrome?: Partial>; + }; + limit?: number; + searchTerm?: string; + startIndex: number; +} + +// Playlist List +export type PlaylistListResponse = BasePaginatedResponse | null | undefined; + +export type RatingQuery = { + item: AnyLibraryItems; + rating: number; +}; + +// Rating +export type RatingResponse = null | undefined; + +export type RemoveFromPlaylistArgs = BaseEndpointArgs & { + query: RemoveFromPlaylistQuery; + serverId?: string; +}; + +export type RemoveFromPlaylistQuery = { id: string; + songId: string[]; +}; + +// Remove from playlist +export type RemoveFromPlaylistResponse = null | undefined; + +export type SetRatingArgs = BaseEndpointArgs & { query: RatingQuery; serverId?: string }; + +export type ShareItemArgs = BaseEndpointArgs & { body: ShareItemBody; serverId?: string }; + +export type ShareItemBody = { + description: string; + downloadable: boolean; + expires: number; + resourceIds: string; + resourceType: string; +}; + +// Sharing +export type ShareItemResponse = undefined | { id: string }; + +export type UpdatePlaylistArgs = BaseEndpointArgs & { + body: UpdatePlaylistBody; + query: UpdatePlaylistQuery; + serverId?: string; }; export type UpdatePlaylistBody = { @@ -865,45 +899,12 @@ export type UpdatePlaylistBody = { public?: boolean; }; -export type UpdatePlaylistArgs = { - body: UpdatePlaylistBody; - query: UpdatePlaylistQuery; - serverId?: string; -} & BaseEndpointArgs; +export type UpdatePlaylistQuery = { + id: string; +}; -// Delete Playlist -export type DeletePlaylistResponse = null | undefined; - -export type DeletePlaylistQuery = { id: string }; - -export type DeletePlaylistArgs = { - query: DeletePlaylistQuery; - serverId?: string; -} & BaseEndpointArgs; - -// Playlist List -export type PlaylistListResponse = BasePaginatedResponse | null | undefined; - -export enum PlaylistListSort { - DURATION = 'duration', - NAME = 'name', - OWNER = 'owner', - PUBLIC = 'public', - SONG_COUNT = 'songCount', - UPDATED_AT = 'updatedAt', -} - -export interface PlaylistListQuery extends BaseQuery { - _custom?: { - jellyfin?: Partial>; - navidrome?: Partial>; - }; - limit?: number; - searchTerm?: string; - startIndex: number; -} - -export type PlaylistListArgs = { query: PlaylistListQuery } & BaseEndpointArgs; +// Update Playlist +export type UpdatePlaylistResponse = null | undefined; type PlaylistListSortMap = { jellyfin: Record; @@ -938,17 +939,27 @@ export const playlistListSortMap: PlaylistListSortMap = { }, }; -// Playlist Detail -export type PlaylistDetailResponse = Playlist; +export enum UserListSort { + NAME = 'name', +} + +export type MusicFolderListArgs = BaseEndpointArgs; + +export type MusicFolderListQuery = null; + +// Music Folder List +export type MusicFolderListResponse = BasePaginatedResponse | null | undefined; + +export type PlaylistDetailArgs = BaseEndpointArgs & { query: PlaylistDetailQuery }; export type PlaylistDetailQuery = { id: string; }; -export type PlaylistDetailArgs = { query: PlaylistDetailQuery } & BaseEndpointArgs; +// Playlist Detail +export type PlaylistDetailResponse = Playlist; -// Playlist Songs -export type PlaylistSongListResponse = BasePaginatedResponse | null | undefined; +export type PlaylistSongListArgs = BaseEndpointArgs & { query: PlaylistSongListQuery }; export type PlaylistSongListQuery = { id: string; @@ -958,22 +969,10 @@ export type PlaylistSongListQuery = { startIndex: number; }; -export type PlaylistSongListArgs = { query: PlaylistSongListQuery } & BaseEndpointArgs; +// Playlist Songs +export type PlaylistSongListResponse = BasePaginatedResponse | null | undefined; -// Music Folder List -export type MusicFolderListResponse = BasePaginatedResponse | null | undefined; - -export type MusicFolderListQuery = null; - -export type MusicFolderListArgs = BaseEndpointArgs; - -// User list -// Playlist List -export type UserListResponse = BasePaginatedResponse | null | undefined; - -export enum UserListSort { - NAME = 'name', -} +export type UserListArgs = BaseEndpointArgs & { query: UserListQuery }; export interface UserListQuery extends BaseQuery { _custom?: { @@ -986,7 +985,9 @@ export interface UserListQuery extends BaseQuery { startIndex: number; } -export type UserListArgs = { query: UserListQuery } & BaseEndpointArgs; +// User list +// Playlist List +export type UserListResponse = BasePaginatedResponse | null | undefined; type UserListSortMap = { jellyfin: Record; @@ -1006,16 +1007,13 @@ export const userListSortMap: UserListSortMap = { }, }; -// Top Songs List -export type TopSongListResponse = BasePaginatedResponse | null | undefined; +export enum Played { + All = 'all', + Never = 'never', + Played = 'played', +} -export type TopSongListQuery = { - artist: string; - artistId: string; - limit?: number; -}; - -export type TopSongListArgs = { query: TopSongListQuery } & BaseEndpointArgs; +export type ArtistInfoArgs = BaseEndpointArgs & { query: ArtistInfoQuery }; // Artist Info export type ArtistInfoQuery = { @@ -1024,98 +1022,12 @@ export type ArtistInfoQuery = { musicFolderId?: string; }; -export type ArtistInfoArgs = { query: ArtistInfoQuery } & BaseEndpointArgs; - -// Scrobble -export type ScrobbleResponse = null | undefined; - -export type ScrobbleArgs = { - query: ScrobbleQuery; - serverId?: string; -} & BaseEndpointArgs; - -export type ScrobbleQuery = { - event?: 'pause' | 'unpause' | 'timeupdate' | 'start'; - id: string; - position?: number; - submission: boolean; +export type FullLyricsMetadata = Omit & { + lyrics: LyricsResponse; + remote: boolean; + source: string; }; -export type SearchQuery = { - albumArtistLimit?: number; - albumArtistStartIndex?: number; - albumLimit?: number; - albumStartIndex?: number; - musicFolderId?: string; - query?: string; - songLimit?: number; - songStartIndex?: number; -}; - -export type SearchSongsQuery = { - musicFolderId?: string; - query?: string; - songLimit?: number; - songStartIndex?: number; -}; - -export type SearchAlbumsQuery = { - albumLimit?: number; - albumStartIndex?: number; - musicFolderId?: string; - query?: string; -}; - -export type SearchAlbumArtistsQuery = { - albumArtistLimit?: number; - albumArtistStartIndex?: number; - musicFolderId?: string; - query?: string; -}; - -export type SearchArgs = { - query: SearchQuery; -} & BaseEndpointArgs; - -export type SearchResponse = { - albumArtists: AlbumArtist[]; - albums: Album[]; - songs: Song[]; -}; - -export enum Played { - All = 'all', - Never = 'never', - Played = 'played', -} - -export type RandomSongListQuery = { - genre?: string; - limit?: number; - maxYear?: number; - minYear?: number; - musicFolderId?: string; - played: Played; -}; - -export type RandomSongListArgs = { - query: RandomSongListQuery; -} & BaseEndpointArgs; - -export type RandomSongListResponse = SongListResponse; - -export type LyricsQuery = { - songId: string; -}; - -export type LyricsArgs = { - query: LyricsQuery; -} & BaseEndpointArgs; - -export type SynchronizedLyricsArray = Array<[number, string]>; - -export type LyricsResponse = SynchronizedLyricsArray | string; - export type InternetProviderLyricResponse = { artist: string; id: string; @@ -1132,132 +1044,113 @@ export type InternetProviderLyricSearchResponse = { source: LyricSource; }; -export type FullLyricsMetadata = { - lyrics: LyricsResponse; - remote: boolean; - source: string; -} & Omit; - export type LyricOverride = Omit; +export type LyricsArgs = BaseEndpointArgs & { + query: LyricsQuery; +}; + +export type LyricsQuery = { + songId: string; +}; + +export type LyricsResponse = string | SynchronizedLyricsArray; + +export type RandomSongListArgs = BaseEndpointArgs & { + query: RandomSongListQuery; +}; + +export type RandomSongListQuery = { + genre?: string; + limit?: number; + maxYear?: number; + minYear?: number; + musicFolderId?: string; + played: Played; +}; + +export type RandomSongListResponse = SongListResponse; + +export type ScrobbleArgs = BaseEndpointArgs & { + query: ScrobbleQuery; + serverId?: string; +}; + +export type ScrobbleQuery = { + event?: 'pause' | 'start' | 'timeupdate' | 'unpause'; + id: string; + position?: number; + submission: boolean; +}; + +// Scrobble +export type ScrobbleResponse = null | undefined; + +export type SearchAlbumArtistsQuery = { + albumArtistLimit?: number; + albumArtistStartIndex?: number; + musicFolderId?: string; + query?: string; +}; + +export type SearchAlbumsQuery = { + albumLimit?: number; + albumStartIndex?: number; + musicFolderId?: string; + query?: string; +}; + +export type SearchArgs = BaseEndpointArgs & { + query: SearchQuery; +}; + +export type SearchQuery = { + albumArtistLimit?: number; + albumArtistStartIndex?: number; + albumLimit?: number; + albumStartIndex?: number; + musicFolderId?: string; + query?: string; + songLimit?: number; + songStartIndex?: number; +}; + +export type SearchResponse = { + albumArtists: AlbumArtist[]; + albums: Album[]; + songs: Song[]; +}; + +export type SearchSongsQuery = { + musicFolderId?: string; + query?: string; + songLimit?: number; + songStartIndex?: number; +}; + +export type SynchronizedLyricsArray = Array<[number, string]>; + +export type TopSongListArgs = BaseEndpointArgs & { query: TopSongListQuery }; + +export type TopSongListQuery = { + artist: string; + artistId: string; + limit?: number; +}; + +// Top Songs List +export type TopSongListResponse = BasePaginatedResponse | null | undefined; + export const instanceOfCancellationError = (error: any) => { return 'revert' in error; }; -export type LyricSearchQuery = { - album?: string; - artist?: string; - duration?: number; - name?: string; -}; - -export type LyricGetQuery = { - remoteSongId: string; - remoteSource: LyricSource; - song: Song; -}; - export enum LyricSource { GENIUS = 'Genius', LRCLIB = 'lrclib.net', NETEASE = 'NetEase', } -export type LyricsOverride = Omit & { id: string }; - -// This type from https://wicg.github.io/local-font-access/#fontdata -// NOTE: it is still experimental, so this should be updates as appropriate -export type FontData = { - family: string; - fullName: string; - postscriptName: string; - style: string; -}; - -export type ServerInfoArgs = BaseEndpointArgs; - -export type ServerInfo = { - features: ServerFeatures; - id?: string; - version: string; -}; - -export type StructuredLyricsArgs = { - query: LyricsQuery; -} & BaseEndpointArgs; - -export type StructuredUnsyncedLyric = { - lyrics: string; - synced: false; -} & Omit; - -export type StructuredSyncedLyric = { - lyrics: SynchronizedLyricsArray; - synced: true; -} & Omit; - -export type StructuredLyric = { - lang: string; -} & (StructuredUnsyncedLyric | StructuredSyncedLyric); - -export type SimilarSongsQuery = { - albumArtistIds: string[]; - count?: number; - songId: string; -}; - -export type SimilarSongsArgs = { - query: SimilarSongsQuery; -} & BaseEndpointArgs; - -export type MoveItemQuery = { - endingIndex: number; - playlistId: string; - startingIndex: number; - trackId: string; -}; - -export type MoveItemArgs = { - query: MoveItemQuery; -} & BaseEndpointArgs; - -export type DownloadQuery = { - id: string; -}; - -export type DownloadArgs = { - query: DownloadQuery; -} & BaseEndpointArgs; - -export type TranscodingQuery = { - base: string; - bitrate?: number; - format?: string; -}; - -export type TranscodingArgs = { - query: TranscodingQuery; -} & BaseEndpointArgs; - -export type TagQuery = { - folder?: string; - type: LibraryItem.ALBUM | LibraryItem.SONG; -}; - -export type TagArgs = { - query: TagQuery; -} & BaseEndpointArgs; - -export type Tag = { - name: string; - options: string[]; -}; - -export type TagResponses = { - boolTags?: string[]; - enumTags?: Tag[]; -}; - export type ControllerEndpoint = { addToPlaylist: (args: AddToPlaylistArgs) => Promise; authenticate: ( @@ -1307,6 +1200,114 @@ export type ControllerEndpoint = { updatePlaylist: (args: UpdatePlaylistArgs) => Promise; }; +export type DownloadArgs = BaseEndpointArgs & { + query: DownloadQuery; +}; + +export type DownloadQuery = { + id: string; +}; + +// This type from https://wicg.github.io/local-font-access/#fontdata +// NOTE: it is still experimental, so this should be updates as appropriate +export type FontData = { + family: string; + fullName: string; + postscriptName: string; + style: string; +}; + +export type LyricGetQuery = { + remoteSongId: string; + remoteSource: LyricSource; + song: Song; +}; + +export type LyricSearchQuery = { + album?: string; + artist?: string; + duration?: number; + name?: string; +}; + +export type LyricsOverride = Omit & { id: string }; + +export type MoveItemArgs = BaseEndpointArgs & { + query: MoveItemQuery; +}; + +export type MoveItemQuery = { + endingIndex: number; + playlistId: string; + startingIndex: number; + trackId: string; +}; + +export type ServerInfo = { + features: ServerFeatures; + id?: string; + version: string; +}; + +export type ServerInfoArgs = BaseEndpointArgs; + +export type SimilarSongsArgs = BaseEndpointArgs & { + query: SimilarSongsQuery; +}; + +export type SimilarSongsQuery = { + albumArtistIds: string[]; + count?: number; + songId: string; +}; + +export type StructuredLyric = (StructuredSyncedLyric | StructuredUnsyncedLyric) & { + lang: string; +}; + +export type StructuredLyricsArgs = BaseEndpointArgs & { + query: LyricsQuery; +}; + +export type StructuredSyncedLyric = Omit & { + lyrics: SynchronizedLyricsArray; + synced: true; +}; + +export type StructuredUnsyncedLyric = Omit & { + lyrics: string; + synced: false; +}; + +export type Tag = { + name: string; + options: string[]; +}; + +export type TagArgs = BaseEndpointArgs & { + query: TagQuery; +}; + +export type TagQuery = { + folder?: string; + type: LibraryItem.ALBUM | LibraryItem.SONG; +}; + +export type TagResponses = { + boolTags?: string[]; + enumTags?: Tag[]; +}; + +export type TranscodingArgs = BaseEndpointArgs & { + query: TranscodingQuery; +}; + +export type TranscodingQuery = { + base: string; + bitrate?: number; + format?: string; +}; + export const sortAlbumList = (albums: Album[], sortBy: AlbumListSort, sortOrder: SortOrder) => { let results = albums; @@ -1335,21 +1336,21 @@ export const sortAlbumList = (albums: Album[], sortBy: AlbumListSort, sortOrder: case AlbumListSort.RANDOM: results = shuffle(results); break; + case AlbumListSort.RATING: + results = orderBy(results, ['userRating'], [order]); + break; case AlbumListSort.RECENTLY_ADDED: results = orderBy(results, ['createdAt'], [order]); break; case AlbumListSort.RECENTLY_PLAYED: results = orderBy(results, ['lastPlayedAt'], [order]); break; - case AlbumListSort.RATING: - results = orderBy(results, ['userRating'], [order]); + case AlbumListSort.SONG_COUNT: + results = orderBy(results, ['songCount'], [order]); break; case AlbumListSort.YEAR: results = orderBy(results, ['releaseYear'], [order]); break; - case AlbumListSort.SONG_COUNT: - results = orderBy(results, ['songCount'], [order]); - break; default: break; } @@ -1463,14 +1464,14 @@ export const sortAlbumArtistList = ( results = orderBy(artists, ['albumCount', (v) => v.name.toLowerCase()], [order, 'asc']); break; - case AlbumArtistListSort.NAME: - results = orderBy(artists, [(v) => v.name.toLowerCase()], [order]); - break; - case AlbumArtistListSort.FAVORITED: results = orderBy(artists, ['starred'], [order]); break; + case AlbumArtistListSort.NAME: + results = orderBy(artists, [(v) => v.name.toLowerCase()], [order]); + break; + case AlbumArtistListSort.RATING: results = orderBy(artists, ['userRating'], [order]); break; diff --git a/src/renderer/api/utils.ts b/src/renderer/api/utils.ts index d995b18b..00914d12 100644 --- a/src/renderer/api/utils.ts +++ b/src/renderer/api/utils.ts @@ -3,10 +3,11 @@ import isElectron from 'is-electron'; import semverCoerce from 'semver/functions/coerce'; import semverGte from 'semver/functions/gte'; import { z } from 'zod'; + +import { ServerFeature } from '/@/renderer/api/features-types'; +import { ServerListItem } from '/@/renderer/api/types'; import { toast } from '/@/renderer/components/toast'; import { useAuthStore } from '/@/renderer/store'; -import { ServerListItem } from '/@/renderer/api/types'; -import { ServerFeature } from '/@/renderer/api/features-types'; // Since ts-rest client returns a strict response type, we need to add the headers to the body object export const resultWithHeaders = (itemSchema: ItemType) => { @@ -29,7 +30,7 @@ export const resultSubsonicBaseResponse = ( }); }; -export const authenticationFailure = (currentServer: ServerListItem | null) => { +export const authenticationFailure = (currentServer: null | ServerListItem) => { toast.error({ message: 'Your session has expired.', }); @@ -43,7 +44,7 @@ export const authenticationFailure = (currentServer: ServerListItem | null) => { } }; -export const hasFeature = (server: ServerListItem | null, feature: ServerFeature): boolean => { +export const hasFeature = (server: null | ServerListItem, feature: ServerFeature): boolean => { if (!server || !server.features) { return false; } diff --git a/src/renderer/app.tsx b/src/renderer/app.tsx index 6637b28b..b5deb049 100644 --- a/src/renderer/app.tsx +++ b/src/renderer/app.tsx @@ -1,33 +1,39 @@ -import { useEffect, useMemo, useState, useRef } from 'react'; import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model'; import { ModuleRegistry } from '@ag-grid-community/core'; import { InfiniteRowModelModule } from '@ag-grid-community/infinite-row-model'; import { MantineProvider } from '@mantine/core'; import isElectron from 'is-electron'; +import { useEffect, useMemo, useRef, useState } from 'react'; import { initSimpleImg } from 'react-simple-img'; + +import i18n from '../i18n/i18n'; import { toast } from './components'; import { useTheme } from './hooks'; -import { IsUpdatedDialog } from './is-updated-dialog'; import { AppRouter } from './router/app-router'; +import './styles/global.scss'; + +import '@ag-grid-community/styles/ag-grid.css'; +import 'overlayscrollbars/overlayscrollbars.css'; + import { + useCssSettings, useHotkeySettings, usePlaybackSettings, useRemoteSettings, useSettingsStore, } from './store/settings.store'; -import './styles/global.scss'; + import { ContextMenuProvider } from '/@/renderer/features/context-menu'; -import { useHandlePlayQueueAdd } from '/@/renderer/features/player/hooks/use-handle-playqueue-add'; -import { PlayQueueHandlerContext } from '/@/renderer/features/player'; -import { getMpvProperties } from '/@/renderer/features/settings/components/playback/mpv-settings'; -import { PlayerState, useCssSettings, usePlayerStore, useQueueControls } from '/@/renderer/store'; -import { FontType, PlaybackType, PlayerStatus, WebAudio } from '/@/renderer/types'; -import '@ag-grid-community/styles/ag-grid.css'; -import { WebAudioContext } from '/@/renderer/features/player/context/webaudio-context'; import { useDiscordRpc } from '/@/renderer/features/discord-rpc/use-discord-rpc'; -import i18n from '/@/i18n/i18n'; -import { useServerVersion } from '/@/renderer/hooks/use-server-version'; +import { PlayQueueHandlerContext } from '/@/renderer/features/player'; +import { WebAudioContext } from '/@/renderer/features/player/context/webaudio-context'; +import { useHandlePlayQueueAdd } from '/@/renderer/features/player/hooks/use-handle-playqueue-add'; import { updateSong } from '/@/renderer/features/player/update-remote-song'; +import { getMpvProperties } from '/@/renderer/features/settings/components/playback/mpv-settings'; +import { useServerVersion } from '/@/renderer/hooks/use-server-version'; +import { IsUpdatedDialog } from '/@/renderer/is-updated-dialog'; +import { PlayerState, usePlayerStore, useQueueControls } from '/@/renderer/store'; +import { FontType, PlaybackType, PlayerStatus, WebAudio } from '/@/renderer/types'; import { sanitizeCss } from '/@/renderer/utils/sanitize'; import { setQueue } from '/@/renderer/utils/set-transcoded-queue-data'; @@ -35,10 +41,10 @@ ModuleRegistry.registerModules([ClientSideRowModelModule, InfiniteRowModelModule initSimpleImg({ threshold: 0.05 }, true); -const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null; -const ipc = isElectron() ? window.electron.ipc : null; -const remote = isElectron() ? window.electron.remote : null; -const utils = isElectron() ? window.electron.utils : null; +const mpvPlayer = isElectron() ? window.api.mpvPlayer : null; +const ipc = isElectron() ? window.api.ipc : null; +const remote = isElectron() ? window.api.remote : null; +const utils = isElectron() ? window.api.utils : null; export const App = () => { const theme = useTheme(); @@ -46,7 +52,7 @@ export const App = () => { const language = useSettingsStore((store) => store.general.language); const nativeImageAspect = useSettingsStore((store) => store.general.nativeAspectRatio); const { builtIn, custom, system, type } = useSettingsStore((state) => state.font); - const { enabled, content } = useCssSettings(); + const { content, enabled } = useCssSettings(); const { type: playbackType } = usePlaybackSettings(); const { bindings } = useHotkeySettings(); const handlePlayQueueAdd = useHandlePlayQueueAdd(); @@ -230,10 +236,8 @@ export const App = () => { return ( { xs: '0rem', }, }} + withGlobalStyles + withNormalizeCSS > diff --git a/src/renderer/assets/assets.d.ts b/src/renderer/assets/assets.d.ts new file mode 100644 index 00000000..cf652454 --- /dev/null +++ b/src/renderer/assets/assets.d.ts @@ -0,0 +1,31 @@ +type Styles = Record; + +declare module '*.svg' { + const content: string; + export default content; +} + +declare module '*.png' { + const content: string; + export default content; +} + +declare module '*.jpg' { + const content: string; + export default content; +} + +declare module '*.scss' { + const content: Styles; + export default content; +} + +declare module '*.sass' { + const content: Styles; + export default content; +} + +declare module '*.css' { + const content: Styles; + export default content; +} diff --git a/src/renderer/assets/entitlements.mac.plist b/src/renderer/assets/entitlements.mac.plist new file mode 100644 index 00000000..dad3e20e --- /dev/null +++ b/src/renderer/assets/entitlements.mac.plist @@ -0,0 +1,10 @@ + + + + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.allow-jit + + + diff --git a/src/renderer/assets/icons/1024x1024.png b/src/renderer/assets/icons/1024x1024.png new file mode 100644 index 00000000..62563d85 Binary files /dev/null and b/src/renderer/assets/icons/1024x1024.png differ diff --git a/src/renderer/assets/icons/128x128.png b/src/renderer/assets/icons/128x128.png new file mode 100644 index 00000000..6bb49a9b Binary files /dev/null and b/src/renderer/assets/icons/128x128.png differ diff --git a/src/renderer/assets/icons/256x256.png b/src/renderer/assets/icons/256x256.png new file mode 100644 index 00000000..932f7d33 Binary files /dev/null and b/src/renderer/assets/icons/256x256.png differ diff --git a/src/renderer/assets/icons/32x32.png b/src/renderer/assets/icons/32x32.png new file mode 100644 index 00000000..ecdac26b Binary files /dev/null and b/src/renderer/assets/icons/32x32.png differ diff --git a/src/renderer/assets/icons/512x512.png b/src/renderer/assets/icons/512x512.png new file mode 100644 index 00000000..f364f2c1 Binary files /dev/null and b/src/renderer/assets/icons/512x512.png differ diff --git a/src/renderer/assets/icons/64x64.png b/src/renderer/assets/icons/64x64.png new file mode 100644 index 00000000..7534b9f5 Binary files /dev/null and b/src/renderer/assets/icons/64x64.png differ diff --git a/src/renderer/assets/icons/favicon.ico b/src/renderer/assets/icons/favicon.ico new file mode 100644 index 00000000..50d1d236 Binary files /dev/null and b/src/renderer/assets/icons/favicon.ico differ diff --git a/src/renderer/assets/icons/icon.icns b/src/renderer/assets/icons/icon.icns new file mode 100644 index 00000000..93da8771 Binary files /dev/null and b/src/renderer/assets/icons/icon.icns differ diff --git a/src/renderer/assets/icons/icon.ico b/src/renderer/assets/icons/icon.ico new file mode 100644 index 00000000..1e9d1e04 Binary files /dev/null and b/src/renderer/assets/icons/icon.ico differ diff --git a/src/renderer/assets/icons/icon.png b/src/renderer/assets/icons/icon.png new file mode 100644 index 00000000..f364f2c1 Binary files /dev/null and b/src/renderer/assets/icons/icon.png differ diff --git a/src/renderer/assets/pause-circle.png b/src/renderer/assets/pause-circle.png new file mode 100644 index 00000000..2636f00b Binary files /dev/null and b/src/renderer/assets/pause-circle.png differ diff --git a/src/renderer/assets/play-circle.png b/src/renderer/assets/play-circle.png new file mode 100644 index 00000000..0d10870e Binary files /dev/null and b/src/renderer/assets/play-circle.png differ diff --git a/src/renderer/assets/skip-next.png b/src/renderer/assets/skip-next.png new file mode 100644 index 00000000..438fb3a3 Binary files /dev/null and b/src/renderer/assets/skip-next.png differ diff --git a/src/renderer/assets/skip-previous.png b/src/renderer/assets/skip-previous.png new file mode 100644 index 00000000..14088508 Binary files /dev/null and b/src/renderer/assets/skip-previous.png differ diff --git a/src/renderer/components/accordion/index.tsx b/src/renderer/components/accordion/index.tsx index 63132d23..8a579c72 100644 --- a/src/renderer/components/accordion/index.tsx +++ b/src/renderer/components/accordion/index.tsx @@ -1,4 +1,5 @@ import type { AccordionProps as MantineAccordionProps } from '@mantine/core'; + import { Accordion as MantineAccordion } from '@mantine/core'; import styled from 'styled-components'; diff --git a/src/renderer/components/audio-player/index.tsx b/src/renderer/components/audio-player/index.tsx index 87e0e20e..fedb6c9a 100644 --- a/src/renderer/components/audio-player/index.tsx +++ b/src/renderer/components/audio-player/index.tsx @@ -1,27 +1,36 @@ +import type { Song } from '/@/renderer/api/types'; +import type { CrossfadeStyle } from '/@/renderer/types'; +import type { ReactPlayerProps } from 'react-player'; + +import isElectron from 'is-electron'; import { - useImperativeHandle, forwardRef, - useRef, - useState, useCallback, useEffect, + useImperativeHandle, useMemo, + useRef, + useState, } from 'react'; -import isElectron from 'is-electron'; -import type { ReactPlayerProps } from 'react-player'; import ReactPlayer from 'react-player/lazy'; -import type { Song } from '/@/renderer/api/types'; + +import { api } from '/@/renderer/api'; import { crossfadeHandler, gaplessHandler, } from '/@/renderer/components/audio-player/utils/list-handlers'; -import { useSettingsStore, useSettingsStoreActions } from '/@/renderer/store/settings.store'; -import type { CrossfadeStyle } from '/@/renderer/types'; -import { PlaybackStyle, PlayerStatus } from '/@/renderer/types'; +import { toast } from '/@/renderer/components/toast'; import { useWebAudio } from '/@/renderer/features/player/hooks/use-webaudio'; import { getServerById, TranscodingConfig, usePlaybackSettings, useSpeed } from '/@/renderer/store'; -import { toast } from '/@/renderer/components/toast'; -import { api } from '/@/renderer/api'; +import { useSettingsStore, useSettingsStoreActions } from '/@/renderer/store/settings.store'; +import { PlaybackStyle, PlayerStatus } from '/@/renderer/types'; + +export type AudioPlayerProgress = { + loaded: number; + loadedSeconds: number; + played: number; + playedSeconds: number; +}; interface AudioPlayerProps extends ReactPlayerProps { crossfadeDuration: number; @@ -34,13 +43,6 @@ interface AudioPlayerProps extends ReactPlayerProps { volume: number; } -export type AudioPlayerProgress = { - loaded: number; - loadedSeconds: number; - played: number; - playedSeconds: number; -}; - const getDuration = (ref: any) => { return ref.current?.player?.player?.player?.duration; }; @@ -53,7 +55,7 @@ const getDuration = (ref: any) => { const EMPTY_SOURCE = 'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU2LjM2LjEwMAAAAAAAAAAAAAAA//OEAAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAAEAAABIADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV6urq6urq6urq6urq6urq6urq6urq6urq6v////////////////////////////////8AAAAATGF2YzU2LjQxAAAAAAAAAAAAAAAAJAAAAAAAAAAAASDs90hvAAAAAAAAAAAAAAAAAAAA//MUZAAAAAGkAAAAAAAAA0gAAAAATEFN//MUZAMAAAGkAAAAAAAAA0gAAAAARTMu//MUZAYAAAGkAAAAAAAAA0gAAAAAOTku//MUZAkAAAGkAAAAAAAAA0gAAAAANVVV'; -const useSongUrl = (transcode: TranscodingConfig, current: boolean, song?: Song): string | null => { +const useSongUrl = (transcode: TranscodingConfig, current: boolean, song?: Song): null | string => { const prior = useRef(['', '']); return useMemo(() => { @@ -94,15 +96,15 @@ const useSongUrl = (transcode: TranscodingConfig, current: boolean, song?: Song) export const AudioPlayer = forwardRef( ( { - status, - playbackStyle, - crossfadeStyle, - crossfadeDuration, - currentPlayer, autoNext, + crossfadeDuration, + crossfadeStyle, + currentPlayer, + muted, + playbackStyle, player1, player2, - muted, + status, volume, }: AudioPlayerProps, ref: any, @@ -120,7 +122,7 @@ export const AudioPlayer = forwardRef( const stream1 = useSongUrl(transcode, currentPlayer === 1, player1); const stream2 = useSongUrl(transcode, currentPlayer === 2, player2); - const { webAudio, setWebAudio } = useWebAudio(); + const { setWebAudio, webAudio } = useWebAudio(); const [player1Source, setPlayer1Source] = useState( null, ); @@ -415,43 +417,43 @@ export const AudioPlayer = forwardRef( return ( <> ); diff --git a/src/renderer/components/audio-player/utils/list-handlers.ts b/src/renderer/components/audio-player/utils/list-handlers.ts index a22b0fa9..89c96bb6 100644 --- a/src/renderer/components/audio-player/utils/list-handlers.ts +++ b/src/renderer/components/audio-player/utils/list-handlers.ts @@ -1,5 +1,5 @@ -/* eslint-disable no-nested-ternary */ import type { Dispatch } from 'react'; + import { CrossfadeStyle } from '/@/renderer/types'; export const gaplessHandler = (args: { @@ -10,7 +10,7 @@ export const gaplessHandler = (args: { nextPlayerRef: any; setIsTransitioning: Dispatch; }) => { - const { nextPlayerRef, currentTime, duration, isTransitioning, setIsTransitioning, isFlac } = + const { currentTime, duration, isFlac, isTransitioning, nextPlayerRef, setIsTransitioning } = args; if (!isTransitioning) { @@ -46,17 +46,17 @@ export const crossfadeHandler = (args: { volume: number; }) => { const { - currentTime, - player, currentPlayer, currentPlayerRef, - nextPlayerRef, + currentTime, + duration, fadeDuration, fadeType, - duration, - volume, isTransitioning, + nextPlayerRef, + player, setIsTransitioning, + volume, } = args; if (!isTransitioning || currentPlayer !== player) { @@ -79,22 +79,18 @@ export const crossfadeHandler = (args: { let percentageOfFadeLeft; let n; switch (fadeType) { - case 'equalPower': - // https://dsp.stackexchange.com/a/14755 - percentageOfFadeLeft = (timeLeft / fadeDuration) * 2; - currentPlayerVolumeCalculation = Math.sqrt(0.5 * percentageOfFadeLeft) * volume; - nextPlayerVolumeCalculation = Math.sqrt(0.5 * (2 - percentageOfFadeLeft)) * volume; - break; - case 'linear': - currentPlayerVolumeCalculation = (timeLeft / fadeDuration) * volume; - nextPlayerVolumeCalculation = ((fadeDuration - timeLeft) / fadeDuration) * volume; - break; case 'dipped': // https://math.stackexchange.com/a/4622 percentageOfFadeLeft = timeLeft / fadeDuration; currentPlayerVolumeCalculation = percentageOfFadeLeft ** 2 * volume; nextPlayerVolumeCalculation = (percentageOfFadeLeft - 1) ** 2 * volume; break; + case 'equalPower': + // https://dsp.stackexchange.com/a/14755 + percentageOfFadeLeft = (timeLeft / fadeDuration) * 2; + currentPlayerVolumeCalculation = Math.sqrt(0.5 * percentageOfFadeLeft) * volume; + nextPlayerVolumeCalculation = Math.sqrt(0.5 * (2 - percentageOfFadeLeft)) * volume; + break; case fadeType.match(/constantPower.*/)?.input: // https://math.stackexchange.com/a/26159 n = @@ -114,6 +110,10 @@ export const crossfadeHandler = (args: { Math.cos((Math.PI / 4) * ((2 * percentageOfFadeLeft - 1) ** (2 * n + 1) + 1)) * volume; break; + case 'linear': + currentPlayerVolumeCalculation = (timeLeft / fadeDuration) * volume; + nextPlayerVolumeCalculation = ((fadeDuration - timeLeft) / fadeDuration) * volume; + break; default: currentPlayerVolumeCalculation = (timeLeft / fadeDuration) * volume; diff --git a/src/renderer/components/badge/index.tsx b/src/renderer/components/badge/index.tsx index 2343f744..309298db 100644 --- a/src/renderer/components/badge/index.tsx +++ b/src/renderer/components/badge/index.tsx @@ -1,4 +1,5 @@ import type { BadgeProps as MantineBadgeProps } from '@mantine/core'; + import { createPolymorphicComponent, Badge as MantineBadge } from '@mantine/core'; import styled from 'styled-components'; diff --git a/src/renderer/components/button/index.tsx b/src/renderer/components/button/index.tsx index 41bf1638..29d67b6d 100644 --- a/src/renderer/components/button/index.tsx +++ b/src/renderer/components/button/index.tsx @@ -1,9 +1,11 @@ -import type { Ref } from 'react'; -import React, { useRef, useCallback, useState, forwardRef } from 'react'; import type { ButtonProps as MantineButtonProps, TooltipProps } from '@mantine/core'; -import { Button as MantineButton, createPolymorphicComponent } from '@mantine/core'; +import type { Ref } from 'react'; + +import { createPolymorphicComponent, Button as MantineButton } from '@mantine/core'; import { useTimeout } from '@mantine/hooks'; +import React, { forwardRef, useCallback, useRef, useState } from 'react'; import styled from 'styled-components'; + import { Spinner } from '/@/renderer/components/spinner'; import { Tooltip } from '/@/renderer/components/tooltip'; @@ -94,8 +96,8 @@ export const _Button = forwardRef( {...tooltip} > {children} @@ -111,8 +113,8 @@ export const _Button = forwardRef( return ( {children} @@ -153,7 +155,7 @@ export const TimeoutButton = ({ timeoutProps, ...props }: HoldButtonProps) => { setIsRunning(false); }; - const { start, clear } = useTimeout(callback, timeoutProps.duration); + const { clear, start } = useTimeout(callback, timeoutProps.duration); const startTimeout = useCallback(() => { if (isRunning) { @@ -174,8 +176,8 @@ export const TimeoutButton = ({ timeoutProps, ...props }: HoldButtonProps) => { return ( diff --git a/src/renderer/components/grid-carousel/index.tsx b/src/renderer/components/grid-carousel/index.tsx index 78f5bd17..6bf6e94c 100644 --- a/src/renderer/components/grid-carousel/index.tsx +++ b/src/renderer/components/grid-carousel/index.tsx @@ -1,3 +1,5 @@ +import { Group, Stack } from '@mantine/core'; +import throttle from 'lodash/throttle'; import { isValidElement, memo, @@ -9,14 +11,13 @@ import { useRef, useState, } from 'react'; -import { Group, Stack } from '@mantine/core'; -import throttle from 'lodash/throttle'; import { RiArrowLeftSLine, RiArrowRightSLine } from 'react-icons/ri'; import styled from 'styled-components'; import { SwiperOptions, Virtual } from 'swiper'; import 'swiper/css'; import { Swiper, SwiperSlide } from 'swiper/react'; import { Swiper as SwiperCore } from 'swiper/types'; + import { Album, AlbumArtist, Artist, LibraryItem, RelatedArtist } from '/@/renderer/api/types'; import { Button } from '/@/renderer/components/button'; import { PosterCard } from '/@/renderer/components/card/poster-card'; @@ -44,14 +45,14 @@ const CarouselContainer = styled(Stack)` interface TitleProps { handleNext?: () => void; handlePrev?: () => void; - label?: string | ReactNode; + label?: ReactNode | string; pagination: { hasNextPage: boolean; hasPreviousPage: boolean; }; } -const Title = ({ label, handleNext, handlePrev, pagination }: TitleProps) => { +const Title = ({ handleNext, handlePrev, label, pagination }: TitleProps) => { return ( {isValidElement(label) ? ( @@ -69,18 +70,18 @@ const Title = ({ label, handleNext, handlePrev, pagination }: TitleProps) => { @@ -90,7 +91,7 @@ const Title = ({ label, handleNext, handlePrev, pagination }: TitleProps) => { }; export interface SwiperGridCarouselProps { - cardRows: CardRow[] | CardRow[] | CardRow[]; + cardRows: CardRow[] | CardRow[] | CardRow[]; data: Album[] | AlbumArtist[] | Artist[] | RelatedArtist[] | undefined; isLoading?: boolean; itemType: LibraryItem; @@ -100,7 +101,7 @@ export interface SwiperGridCarouselProps { children?: ReactNode; hasPagination?: boolean; icon?: ReactNode; - label: string | ReactNode; + label: ReactNode | string; }; uniqueId: string; } @@ -108,15 +109,15 @@ export interface SwiperGridCarouselProps { export const SwiperGridCarousel = ({ cardRows, data, + isLoading, itemType, route, swiperProps, title, - isLoading, uniqueId, }: SwiperGridCarouselProps) => { const containerRef = useRef(null); - const swiperRef = useRef(null); + const swiperRef = useRef(null); const playButtonBehavior = usePlayButtonBehavior(); const handlePlayQueueAdd = usePlayQueueAdd(); const [slideCount, setSlideCount] = useState(4); @@ -140,7 +141,7 @@ export const SwiperGridCarousel = ({ itemType: LibraryItem; serverId: string; }) => { - const { id, itemType, isFavorite, serverId } = options; + const { id, isFavorite, itemType, serverId } = options; if (isFavorite) { deleteFavoriteMutation.mutate({ query: { @@ -205,7 +206,7 @@ export const SwiperGridCarousel = ({ }, [slideCount, swiperProps?.slidesPerView]); const handleOnSlideChange = useCallback((e: SwiperCore) => { - const { slides, isEnd, isBeginning, params } = e; + const { isBeginning, isEnd, params, slides } = e; if (isEnd || isBeginning) return; const slideCount = (params.slidesPerView as number | undefined) || 4; @@ -216,7 +217,7 @@ export const SwiperGridCarousel = ({ }, []); const handleOnZoomChange = useCallback((e: SwiperCore) => { - const { slides, isEnd, isBeginning, params } = e; + const { isBeginning, isEnd, params, slides } = e; if (isEnd || isBeginning) return; const slideCount = (params.slidesPerView as number | undefined) || 4; @@ -227,7 +228,7 @@ export const SwiperGridCarousel = ({ }, []); const handleOnReachEnd = useCallback((e: SwiperCore) => { - const { slides, params } = e; + const { params, slides } = e; const slideCount = (params.slidesPerView as number | undefined) || 4; setPagination({ @@ -237,7 +238,7 @@ export const SwiperGridCarousel = ({ }, []); const handleOnReachBeginning = useCallback((e: SwiperCore) => { - const { slides, params } = e; + const { params, slides } = e; const slideCount = (params.slidesPerView as number | undefined) || 4; setPagination({ @@ -279,8 +280,8 @@ export const SwiperGridCarousel = ({ return ( {title ? ( @@ -292,12 +293,7 @@ export const SwiperGridCarousel = ({ /> ) : null} { swiperRef.current = swiper; }} @@ -305,6 +301,11 @@ export const SwiperGridCarousel = ({ onReachEnd={handleOnReachEnd} onSlideChange={handleOnSlideChange} onZoomChange={handleOnZoomChange} + ref={swiperRef} + resizeObserver + slidesPerView={slideCount} + spaceBetween={20} + style={{ height: '100%', width: '100%' }} {...swiperProps} > {slides.map((slideContent, index) => { diff --git a/src/renderer/components/hover-card/index.tsx b/src/renderer/components/hover-card/index.tsx index 7de932b7..713800b8 100644 --- a/src/renderer/components/hover-card/index.tsx +++ b/src/renderer/components/hover-card/index.tsx @@ -1,4 +1,4 @@ -import { HoverCard as MantineHoverCard, HoverCardProps } from '@mantine/core'; +import { HoverCardProps, HoverCard as MantineHoverCard } from '@mantine/core'; export const HoverCard = ({ children, ...props }: HoverCardProps) => { return ( diff --git a/src/renderer/components/input/index.tsx b/src/renderer/components/input/index.tsx index 94e1d1e1..9cd82ef4 100644 --- a/src/renderer/components/input/index.tsx +++ b/src/renderer/components/input/index.tsx @@ -1,23 +1,30 @@ -import React, { forwardRef } from 'react'; import type { - TextInputProps as MantineTextInputProps, - NumberInputProps as MantineNumberInputProps, - PasswordInputProps as MantinePasswordInputProps, FileInputProps as MantineFileInputProps, JsonInputProps as MantineJsonInputProps, + NumberInputProps as MantineNumberInputProps, + PasswordInputProps as MantinePasswordInputProps, TextareaProps as MantineTextareaProps, + TextInputProps as MantineTextInputProps, } from '@mantine/core'; + import { - TextInput as MantineTextInput, - NumberInput as MantineNumberInput, - PasswordInput as MantinePasswordInput, FileInput as MantineFileInput, JsonInput as MantineJsonInput, + NumberInput as MantineNumberInput, + PasswordInput as MantinePasswordInput, Textarea as MantineTextarea, + TextInput as MantineTextInput, } from '@mantine/core'; +import React, { forwardRef } from 'react'; import styled from 'styled-components'; -interface TextInputProps extends MantineTextInputProps { +interface FileInputProps extends MantineFileInputProps { + children?: React.ReactNode; + maxWidth?: number | string; + width?: number | string; +} + +interface JsonInputProps extends MantineJsonInputProps { children?: React.ReactNode; maxWidth?: number | string; width?: number | string; @@ -35,24 +42,18 @@ interface PasswordInputProps extends MantinePasswordInputProps { width?: number | string; } -interface FileInputProps extends MantineFileInputProps { - children?: React.ReactNode; - maxWidth?: number | string; - width?: number | string; -} - -interface JsonInputProps extends MantineJsonInputProps { - children?: React.ReactNode; - maxWidth?: number | string; - width?: number | string; -} - interface TextareaProps extends MantineTextareaProps { children?: React.ReactNode; maxWidth?: number | string; width?: number | string; } +interface TextInputProps extends MantineTextInputProps { + children?: React.ReactNode; + maxWidth?: number | string; + width?: number | string; +} + const StyledTextInput = styled(MantineTextInput)` & .mantine-TextInput-wrapper { border-color: var(--primary-color); @@ -276,7 +277,7 @@ const StyledTextarea = styled(MantineTextarea)` `; export const TextInput = forwardRef( - ({ children, width, maxWidth, ...props }: TextInputProps, ref) => { + ({ children, maxWidth, width, ...props }: TextInputProps, ref) => { return ( ( ); export const NumberInput = forwardRef( - ({ children, width, maxWidth, ...props }: NumberInputProps, ref) => { + ({ children, maxWidth, width, ...props }: NumberInputProps, ref) => { return ( ( ); export const PasswordInput = forwardRef( - ({ children, width, maxWidth, ...props }: PasswordInputProps, ref) => { + ({ children, maxWidth, width, ...props }: PasswordInputProps, ref) => { return ( ( ); export const FileInput = forwardRef( - ({ children, width, maxWidth, ...props }: FileInputProps, ref) => { + ({ children, maxWidth, width, ...props }: FileInputProps, ref) => { return ( ( ); export const JsonInput = forwardRef( - ({ children, width, maxWidth, ...props }: JsonInputProps, ref) => { + ({ children, maxWidth, width, ...props }: JsonInputProps, ref) => { return ( ( ); export const Textarea = forwardRef( - ({ children, width, maxWidth, ...props }: TextareaProps, ref) => { + ({ children, maxWidth, width, ...props }: TextareaProps, ref) => { return ( { @@ -59,12 +60,12 @@ interface ConfirmModalProps { } export const ConfirmModal = ({ - loading, + children, disabled, labels, + loading, onCancel, onConfirm, - children, }: ConfirmModalProps) => { const handleCancel = () => { if (onCancel) { @@ -80,16 +81,16 @@ export const ConfirmModal = ({ diff --git a/src/renderer/components/option/index.tsx b/src/renderer/components/option/index.tsx index cf814a90..5e7e141b 100644 --- a/src/renderer/components/option/index.tsx +++ b/src/renderer/components/option/index.tsx @@ -1,5 +1,5 @@ -import { ReactNode } from 'react'; import { Flex, Group } from '@mantine/core'; +import { ReactNode } from 'react'; export const Option = ({ children }: any) => { return ( diff --git a/src/renderer/components/page-header/index.tsx b/src/renderer/components/page-header/index.tsx index 3605075a..82fa0bac 100644 --- a/src/renderer/components/page-header/index.tsx +++ b/src/renderer/components/page-header/index.tsx @@ -2,6 +2,7 @@ import { Flex, FlexProps } from '@mantine/core'; import { AnimatePresence, motion, Variants } from 'framer-motion'; import { ReactNode, useRef } from 'react'; import styled from 'styled-components'; + import { useShouldPadTitlebar, useTheme } from '/@/renderer/hooks'; import { useWindowSettings } from '/@/renderer/store/settings.store'; import { Platform } from '/@/renderer/types'; @@ -49,7 +50,7 @@ const BackgroundImage = styled.div<{ $background: string }>` background: ${(props) => props.$background || 'var(--titlebar-bg)'}; `; -const BackgroundImageOverlay = styled.div<{ theme: 'light' | 'dark' }>` +const BackgroundImageOverlay = styled.div<{ theme: 'dark' | 'light' }>` position: absolute; top: 0; left: 0; @@ -63,7 +64,7 @@ const BackgroundImageOverlay = styled.div<{ theme: 'light' | 'dark' }>` `; export interface PageHeaderProps - extends Omit { + extends Omit { animated?: boolean; backgroundColor?: string; children?: ReactNode; @@ -93,11 +94,11 @@ const variants: Variants = { export const PageHeader = ({ animated, - position, - height, backgroundColor, - isHidden, children, + height, + isHidden, + position, ...props }: PageHeaderProps) => { const ref = useRef(null); @@ -108,9 +109,9 @@ export const PageHeader = ({ return ( <>
- + )} diff --git a/src/renderer/components/paper/index.tsx b/src/renderer/components/paper/index.tsx index cad38ff2..4162a76a 100644 --- a/src/renderer/components/paper/index.tsx +++ b/src/renderer/components/paper/index.tsx @@ -1,6 +1,7 @@ -import { ReactNode } from 'react'; import type { PaperProps as MantinePaperProps } from '@mantine/core'; + import { Paper as MantinePaper } from '@mantine/core'; +import { ReactNode } from 'react'; import styled from 'styled-components'; export interface PaperProps extends MantinePaperProps { diff --git a/src/renderer/components/popover/index.tsx b/src/renderer/components/popover/index.tsx index 9d30dbba..c72b098d 100644 --- a/src/renderer/components/popover/index.tsx +++ b/src/renderer/components/popover/index.tsx @@ -1,12 +1,13 @@ import type { - PopoverProps as MantinePopoverProps, PopoverDropdownProps as MantinePopoverDropdownProps, + PopoverProps as MantinePopoverProps, } from '@mantine/core'; + import { Popover as MantinePopover } from '@mantine/core'; import styled from 'styled-components'; -type PopoverProps = MantinePopoverProps; type PopoverDropdownProps = MantinePopoverDropdownProps; +type PopoverProps = MantinePopoverProps; const StyledPopover = styled(MantinePopover)``; @@ -21,13 +22,13 @@ const StyledDropdown = styled(MantinePopover.Dropdown)` export const Popover = ({ children, ...props }: PopoverProps) => { return ( {children} diff --git a/src/renderer/components/query-builder/index.tsx b/src/renderer/components/query-builder/index.tsx index f6dab1d9..f2bb3afe 100644 --- a/src/renderer/components/query-builder/index.tsx +++ b/src/renderer/components/query-builder/index.tsx @@ -1,12 +1,13 @@ import { Group, Stack } from '@mantine/core'; -import { Select } from '/@/renderer/components/select'; import { AnimatePresence, motion } from 'framer-motion'; import { RiAddFill, RiAddLine, RiDeleteBinFill, RiMore2Line, RiRestartLine } from 'react-icons/ri'; + +import i18n from '/@/i18n/i18n'; import { Button } from '/@/renderer/components/button'; import { DropdownMenu } from '/@/renderer/components/dropdown-menu'; import { QueryBuilderOption } from '/@/renderer/components/query-builder/query-builder-option'; +import { Select } from '/@/renderer/components/select'; import { QueryBuilderGroup, QueryBuilderRule } from '/@/renderer/types'; -import i18n from '/@/i18n/i18n'; const FILTER_GROUP_OPTIONS_DATA = [ { @@ -63,22 +64,22 @@ interface QueryBuilderProps { export const QueryBuilder = ({ data, + filters, + groupIndex, level, onAddRule, - onDeleteRuleGroup, - onDeleteRule, onAddRuleGroup, - onChangeType, onChangeField, - operators, onChangeOperator, + onChangeType, onChangeValue, onClearFilters, + onDeleteRule, + onDeleteRuleGroup, onResetFilters, + operators, playlists, - groupIndex, uniqueId, - filters, }: QueryBuilderProps) => { const handleAddRule = () => { onAddRule({ groupIndex, level }); @@ -92,7 +93,7 @@ export const QueryBuilder = ({ onDeleteRuleGroup({ groupIndex, level, uniqueId }); }; - const handleChangeType = (value: string | null) => { + const handleChangeType = (value: null | string) => { onChangeType({ groupIndex, level, value }); }; @@ -105,17 +106,17 @@ export const QueryBuilder = ({ { {...props} /> ); + case 'date': + return ( + + ); + case 'dateRange': + return ( + <> + { + const newRange = [e || 0, numberRange[1]]; + setNumberRange(newRange); + onChange(newRange); + }} + width="10%" + /> + { + const newRange = [numberRange[0], e || 0]; + setNumberRange(newRange); + onChange(newRange); + }} + width="10%" + /> + + ); + case 'number': + return ( + + ); case 'playlist': return ( diff --git a/src/renderer/features/albums/context/album-list-context.tsx b/src/renderer/features/albums/context/album-list-context.tsx index 8a232c31..bd7a6bbb 100644 --- a/src/renderer/features/albums/context/album-list-context.tsx +++ b/src/renderer/features/albums/context/album-list-context.tsx @@ -1,4 +1,5 @@ import { createContext, useContext } from 'react'; + import { ListKey } from '/@/renderer/store'; export const AlbumListContext = createContext<{ id?: string; pageKey: ListKey }>({ diff --git a/src/renderer/features/albums/queries/album-detail-query.ts b/src/renderer/features/albums/queries/album-detail-query.ts index 96d7726f..648dd65b 100644 --- a/src/renderer/features/albums/queries/album-detail-query.ts +++ b/src/renderer/features/albums/queries/album-detail-query.ts @@ -1,9 +1,12 @@ -import { useQuery } from '@tanstack/react-query'; -import { queryKeys } from '/@/renderer/api/query-keys'; -import type { QueryHookArgs } from '/@/renderer/lib/react-query'; -import { getServerById } from '../../../store/auth.store'; import type { AlbumDetailQuery } from '/@/renderer/api/types'; +import type { QueryHookArgs } from '/@/renderer/lib/react-query'; + +import { useQuery } from '@tanstack/react-query'; + +import { getServerById } from '../../../store/auth.store'; + import { controller } from '/@/renderer/api/controller'; +import { queryKeys } from '/@/renderer/api/query-keys'; export const useAlbumDetail = (args: QueryHookArgs) => { const { options, query, serverId } = args; diff --git a/src/renderer/features/albums/queries/album-list-count-query.ts b/src/renderer/features/albums/queries/album-list-count-query.ts index e4c13042..2282cb6a 100644 --- a/src/renderer/features/albums/queries/album-list-count-query.ts +++ b/src/renderer/features/albums/queries/album-list-count-query.ts @@ -1,8 +1,10 @@ -import { useQuery } from '@tanstack/react-query'; -import { api } from '/@/renderer/api'; -import { queryKeys } from '/@/renderer/api/query-keys'; import type { AlbumListQuery } from '/@/renderer/api/types'; import type { QueryHookArgs } from '/@/renderer/lib/react-query'; + +import { useQuery } from '@tanstack/react-query'; + +import { api } from '/@/renderer/api'; +import { queryKeys } from '/@/renderer/api/query-keys'; import { getServerById } from '/@/renderer/store'; export const useAlbumListCount = (args: QueryHookArgs) => { diff --git a/src/renderer/features/albums/queries/album-list-query.ts b/src/renderer/features/albums/queries/album-list-query.ts index 8c65b744..7e9c6e63 100644 --- a/src/renderer/features/albums/queries/album-list-query.ts +++ b/src/renderer/features/albums/queries/album-list-query.ts @@ -1,9 +1,11 @@ +import type { AlbumListQuery, AlbumListResponse } from '/@/renderer/api/types'; +import type { QueryHookArgs } from '/@/renderer/lib/react-query'; + import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; + import { api } from '/@/renderer/api'; import { controller } from '/@/renderer/api/controller'; import { queryKeys } from '/@/renderer/api/query-keys'; -import type { AlbumListQuery, AlbumListResponse } from '/@/renderer/api/types'; -import type { QueryHookArgs } from '/@/renderer/lib/react-query'; import { getServerById } from '/@/renderer/store'; export const useAlbumList = (args: QueryHookArgs) => { diff --git a/src/renderer/features/albums/routes/album-detail-route.tsx b/src/renderer/features/albums/routes/album-detail-route.tsx index 8dab5922..660675ac 100644 --- a/src/renderer/features/albums/routes/album-detail-route.tsx +++ b/src/renderer/features/albums/routes/album-detail-route.tsx @@ -1,16 +1,18 @@ -import { NativeScrollArea, Spinner } from '/@/renderer/components'; -import { AnimatedPage, LibraryHeaderBar } from '/@/renderer/features/shared'; -import { useRef } from 'react'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; -import { useAlbumDetail } from '/@/renderer/features/albums/queries/album-detail-query'; + +import { useRef } from 'react'; import { useParams } from 'react-router'; -import { useFastAverageColor } from '/@/renderer/hooks'; + +import { LibraryItem } from '/@/renderer/api/types'; +import { NativeScrollArea, Spinner } from '/@/renderer/components'; import { AlbumDetailContent } from '/@/renderer/features/albums/components/album-detail-content'; import { AlbumDetailHeader } from '/@/renderer/features/albums/components/album-detail-header'; +import { useAlbumDetail } from '/@/renderer/features/albums/queries/album-detail-query'; import { usePlayQueueAdd } from '/@/renderer/features/player'; -import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; -import { LibraryItem } from '/@/renderer/api/types'; +import { AnimatedPage, LibraryHeaderBar } from '/@/renderer/features/shared'; +import { useFastAverageColor } from '/@/renderer/hooks'; import { useCurrentServer, useGeneralSettings } from '/@/renderer/store'; +import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; const AlbumDetailRoute = () => { const tableRef = useRef(null); @@ -49,7 +51,6 @@ const AlbumDetailRoute = () => { return ( { offset: 200, target: headerRef, }} + ref={scrollAreaRef} > { const { t } = useTranslation(); - const gridRef = useRef(null); + const gridRef = useRef(null); const tableRef = useRef(null); const server = useCurrentServer(); const [searchParams] = useSearchParams(); diff --git a/src/renderer/features/albums/routes/dummy-album-detail-route.tsx b/src/renderer/features/albums/routes/dummy-album-detail-route.tsx index e199a22c..998485fc 100644 --- a/src/renderer/features/albums/routes/dummy-album-detail-route.tsx +++ b/src/renderer/features/albums/routes/dummy-album-detail-route.tsx @@ -1,4 +1,19 @@ +import { Box, Center, Group, Stack } from '@mantine/core'; +import { useQuery } from '@tanstack/react-query'; +import { Fragment } from 'react'; +import { useTranslation } from 'react-i18next'; +import { RiErrorWarningLine, RiHeartFill, RiHeartLine, RiMoreFill } from 'react-icons/ri'; +import { generatePath, useParams } from 'react-router'; +import { Link } from 'react-router-dom'; +import { styled } from 'styled-components'; + +import { api } from '/@/renderer/api'; +import { queryKeys } from '/@/renderer/api/query-keys'; +import { LibraryItem, SongDetailResponse } from '/@/renderer/api/types'; import { Button, Spinner, Spoiler, Text } from '/@/renderer/components'; +import { useHandleGeneralContextMenu } from '/@/renderer/features/context-menu'; +import { SONG_ALBUM_PAGE } from '/@/renderer/features/context-menu/context-menu-items'; +import { usePlayQueueAdd } from '/@/renderer/features/player'; import { AnimatedPage, LibraryHeader, @@ -6,27 +21,13 @@ import { useCreateFavorite, useDeleteFavorite, } from '/@/renderer/features/shared'; -import { Fragment } from 'react'; -import { generatePath, useParams } from 'react-router'; import { useContainerQuery, useFastAverageColor } from '/@/renderer/hooks'; -import { usePlayQueueAdd } from '/@/renderer/features/player'; -import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; -import { LibraryItem, SongDetailResponse } from '/@/renderer/api/types'; -import { useCurrentServer } from '/@/renderer/store'; -import { Stack, Group, Box, Center } from '@mantine/core'; -import { Link } from 'react-router-dom'; -import { AppRoute } from '/@/renderer/router/routes'; -import { formatDurationString } from '/@/renderer/utils'; -import { RiErrorWarningLine, RiHeartFill, RiHeartLine, RiMoreFill } from 'react-icons/ri'; -import { replaceURLWithHTMLLinks } from '/@/renderer/utils/linkify'; -import { SONG_ALBUM_PAGE } from '/@/renderer/features/context-menu/context-menu-items'; -import { useHandleGeneralContextMenu } from '/@/renderer/features/context-menu'; -import { styled } from 'styled-components'; import { queryClient } from '/@/renderer/lib/react-query'; -import { useQuery } from '@tanstack/react-query'; -import { api } from '/@/renderer/api'; -import { queryKeys } from '/@/renderer/api/query-keys'; -import { useTranslation } from 'react-i18next'; +import { AppRoute } from '/@/renderer/router/routes'; +import { useCurrentServer } from '/@/renderer/store'; +import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; +import { formatDurationString } from '/@/renderer/utils'; +import { replaceURLWithHTMLLinks } from '/@/renderer/utils/linkify'; const DetailContainer = styled.div` display: flex; @@ -152,17 +153,17 @@ const DummyAlbumDetailRoute = () => { mah="4rem" spacing="md" sx={{ + overflow: 'hidden', WebkitBoxOrient: 'vertical', WebkitLineClamp: 2, - overflow: 'hidden', }} > {detailQuery?.data?.albumArtists.map((artist) => ( { createFavoriteMutation.isLoading || deleteFavoriteMutation.isLoading } - variant="subtle" onClick={handleFavorite} + variant="subtle" > {detailQuery?.data?.userFavorite ? ( { @@ -220,9 +221,9 @@ const DummyAlbumDetailRoute = () => { {detailQuery?.data?.genres?.map((genre) => ( @@ -412,18 +413,18 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten @@ -473,8 +476,8 @@ export const AlbumArtistListHeaderFilters = ({ {t('table.config.view.card', { postProcess: 'sentenceCase', @@ -482,8 +485,8 @@ export const AlbumArtistListHeaderFilters = ({ {t('table.config.view.poster', { postProcess: 'sentenceCase', @@ -491,8 +494,8 @@ export const AlbumArtistListHeaderFilters = ({ {t('table.config.view.table', { postProcess: 'sentenceCase', @@ -563,8 +566,8 @@ export const AlbumArtistListHeaderFilters = ({ defaultValue={table?.columns.map( (column) => column.column, )} - width={300} onChange={handleTableColumns} + width={300} /> diff --git a/src/renderer/features/artists/components/album-artist-list-header.tsx b/src/renderer/features/artists/components/album-artist-list-header.tsx index 6ce0cfd4..5e5aa5f5 100644 --- a/src/renderer/features/artists/components/album-artist-list-header.tsx +++ b/src/renderer/features/artists/components/album-artist-list-header.tsx @@ -1,27 +1,30 @@ -import type { ChangeEvent, MutableRefObject } from 'react'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; +import type { ChangeEvent, MutableRefObject } from 'react'; + import { Flex, Group, Stack } from '@mantine/core'; import debounce from 'lodash/debounce'; import { useTranslation } from 'react-i18next'; + import { FilterBar } from '../../shared/components/filter-bar'; + import { AlbumArtistListQuery, LibraryItem } from '/@/renderer/api/types'; import { PageHeader, SearchInput } from '/@/renderer/components'; import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid'; import { AlbumArtistListHeaderFilters } from '/@/renderer/features/artists/components/album-artist-list-header-filters'; import { LibraryHeaderBar } from '/@/renderer/features/shared'; import { useContainerQuery } from '/@/renderer/hooks'; -import { AlbumArtistListFilter, useCurrentServer } from '/@/renderer/store'; import { useDisplayRefresh } from '/@/renderer/hooks/use-display-refresh'; +import { AlbumArtistListFilter, useCurrentServer } from '/@/renderer/store'; interface AlbumArtistListHeaderProps { - gridRef: MutableRefObject; + gridRef: MutableRefObject; itemCount?: number; tableRef: MutableRefObject; } export const AlbumArtistListHeader = ({ - itemCount, gridRef, + itemCount, tableRef, }: AlbumArtistListHeaderProps) => { const { t } = useTranslation(); @@ -64,8 +67,8 @@ export const AlbumArtistListHeader = ({ diff --git a/src/renderer/features/artists/components/album-artist-list-table-view.tsx b/src/renderer/features/artists/components/album-artist-list-table-view.tsx index 6cf560df..1fd57275 100644 --- a/src/renderer/features/artists/components/album-artist-list-table-view.tsx +++ b/src/renderer/features/artists/components/album-artist-list-table-view.tsx @@ -1,7 +1,10 @@ import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + import { MutableRefObject } from 'react'; + import { useListContext } from '../../../context/list-context'; import { ARTIST_CONTEXT_MENU_ITEMS } from '../../context-menu/context-menu-items'; + import { LibraryItem } from '/@/renderer/api/types'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; import { VirtualTable } from '/@/renderer/components/virtual-table'; diff --git a/src/renderer/features/artists/components/artist-list-content.tsx b/src/renderer/features/artists/components/artist-list-content.tsx index 436184b4..f36af5f7 100644 --- a/src/renderer/features/artists/components/artist-list-content.tsx +++ b/src/renderer/features/artists/components/artist-list-content.tsx @@ -1,10 +1,13 @@ import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + import { lazy, MutableRefObject, Suspense } from 'react'; + +import { useListStoreByKey } from '../../../store/list.store'; + import { Spinner } from '/@/renderer/components'; import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid'; -import { ListDisplayType } from '/@/renderer/types'; -import { useListStoreByKey } from '../../../store/list.store'; import { useListContext } from '/@/renderer/context/list-context'; +import { ListDisplayType } from '/@/renderer/types'; const ArtistListGridView = lazy(() => import('/@/renderer/features/artists/components/artist-list-grid-view').then((module) => ({ @@ -19,12 +22,12 @@ const ArtistListTableView = lazy(() => ); interface ArtistListContentProps { - gridRef: MutableRefObject; + gridRef: MutableRefObject; itemCount?: number; tableRef: MutableRefObject; } -export const ArtistListContent = ({ itemCount, gridRef, tableRef }: ArtistListContentProps) => { +export const ArtistListContent = ({ gridRef, itemCount, tableRef }: ArtistListContentProps) => { const { pageKey } = useListContext(); const { display } = useListStoreByKey({ key: pageKey }); const isGrid = display === ListDisplayType.CARD || display === ListDisplayType.POSTER; diff --git a/src/renderer/features/artists/components/artist-list-grid-view.tsx b/src/renderer/features/artists/components/artist-list-grid-view.tsx index 9734da73..e72a63ca 100644 --- a/src/renderer/features/artists/components/artist-list-grid-view.tsx +++ b/src/renderer/features/artists/components/artist-list-grid-view.tsx @@ -2,8 +2,10 @@ import { QueryKey, useQueryClient } from '@tanstack/react-query'; import { MutableRefObject, useCallback, useMemo } from 'react'; import AutoSizer, { Size } from 'react-virtualized-auto-sizer'; import { ListOnScrollProps } from 'react-window'; + import { VirtualGridAutoSizerContainer } from '../../../components/virtual-grid/virtual-grid-wrapper'; import { useListStoreByKey } from '../../../store/list.store'; + import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { @@ -17,28 +19,28 @@ import { ALBUMARTIST_CARD_ROWS } from '/@/renderer/components'; import { VirtualInfiniteGrid, VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid'; import { useListContext } from '/@/renderer/context/list-context'; import { usePlayQueueAdd } from '/@/renderer/features/player'; +import { useHandleFavorite } from '/@/renderer/features/shared/hooks/use-handle-favorite'; import { AppRoute } from '/@/renderer/router/routes'; import { useCurrentServer, useListStoreActions } from '/@/renderer/store'; import { CardRow, ListDisplayType } from '/@/renderer/types'; -import { useHandleFavorite } from '/@/renderer/features/shared/hooks/use-handle-favorite'; interface ArtistListGridViewProps { - gridRef: MutableRefObject; + gridRef: MutableRefObject; itemCount?: number; } -export const ArtistListGridView = ({ itemCount, gridRef }: ArtistListGridViewProps) => { +export const ArtistListGridView = ({ gridRef, itemCount }: ArtistListGridViewProps) => { const queryClient = useQueryClient(); const server = useCurrentServer(); const handlePlayQueueAdd = usePlayQueueAdd(); const { pageKey } = useListContext(); - const { grid, display, filter } = useListStoreByKey({ key: pageKey }); + const { display, filter, grid } = useListStoreByKey({ key: pageKey }); const { setGrid } = useListStoreActions(); const handleFavorite = useHandleFavorite({ gridRef, server }); const fetchInitialData = useCallback(() => { - const query: Omit = { + const query: Omit = { ...filter, }; @@ -109,6 +111,9 @@ export const ArtistListGridView = ({ itemCount, gridRef }: ArtistListGridViewPro const rows: CardRow[] = [ALBUMARTIST_CARD_ROWS.name]; switch (filter.sortBy) { + case ArtistListSort.ALBUM_COUNT: + rows.push(ALBUMARTIST_CARD_ROWS.albumCount); + break; case ArtistListSort.DURATION: rows.push(ALBUMARTIST_CARD_ROWS.duration); break; @@ -116,9 +121,6 @@ export const ArtistListGridView = ({ itemCount, gridRef }: ArtistListGridViewPro break; case ArtistListSort.NAME: break; - case ArtistListSort.ALBUM_COUNT: - rows.push(ALBUMARTIST_CARD_ROWS.albumCount); - break; case ArtistListSort.PLAY_COUNT: rows.push(ALBUMARTIST_CARD_ROWS.playCount); break; @@ -129,11 +131,11 @@ export const ArtistListGridView = ({ itemCount, gridRef }: ArtistListGridViewPro break; case ArtistListSort.RECENTLY_ADDED: break; + case ArtistListSort.RELEASE_DATE: + break; case ArtistListSort.SONG_COUNT: rows.push(ALBUMARTIST_CARD_ROWS.songCount); break; - case ArtistListSort.RELEASE_DATE: - break; } return rows; @@ -144,7 +146,6 @@ export const ArtistListGridView = ({ itemCount, gridRef }: ArtistListGridViewPro {({ height, width }: Size) => ( )} diff --git a/src/renderer/features/artists/components/artist-list-header-filters.tsx b/src/renderer/features/artists/components/artist-list-header-filters.tsx index a6ac45cf..1551c0d1 100644 --- a/src/renderer/features/artists/components/artist-list-header-filters.tsx +++ b/src/renderer/features/artists/components/artist-list-header-filters.tsx @@ -1,12 +1,16 @@ -import { ChangeEvent, MouseEvent, MutableRefObject, useCallback } from 'react'; -import { IDatasource } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + +import { IDatasource } from '@ag-grid-community/core'; import { Divider, Flex, Group, Stack } from '@mantine/core'; import { useQueryClient } from '@tanstack/react-query'; import debounce from 'lodash/debounce'; +import { ChangeEvent, MouseEvent, MutableRefObject, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { RiFolder2Line, RiMoreFill, RiRefreshLine, RiSettings3Fill } from 'react-icons/ri'; + import { useListContext } from '../../../context/list-context'; + +import i18n from '/@/i18n/i18n'; import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { @@ -27,6 +31,7 @@ import { } from '/@/renderer/components'; import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid'; import { ALBUMARTIST_TABLE_COLUMNS } from '/@/renderer/components/virtual-table'; +import { useRoles } from '/@/renderer/features/artists/queries/roles-query'; import { OrderToggleButton, useMusicFolders } from '/@/renderer/features/shared'; import { useContainerQuery } from '/@/renderer/hooks'; import { @@ -36,8 +41,6 @@ import { useListStoreByKey, } from '/@/renderer/store'; import { ListDisplayType, TableColumn } from '/@/renderer/types'; -import i18n from '/@/i18n/i18n'; -import { useRoles } from '/@/renderer/features/artists/queries/roles-query'; const FILTERS = { jellyfin: [ @@ -124,7 +127,7 @@ const FILTERS = { }; interface ArtistListHeaderFiltersProps { - gridRef: MutableRefObject; + gridRef: MutableRefObject; tableRef: MutableRefObject; } @@ -133,10 +136,10 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF const queryClient = useQueryClient(); const server = useCurrentServer(); const { pageKey } = useListContext(); - const { display, table, grid, filter } = useListStoreByKey({ + const { display, filter, grid, table } = useListStoreByKey({ key: pageKey, }); - const { setFilter, setTable, setTablePagination, setDisplayType, setGrid } = + const { setDisplayType, setFilter, setGrid, setTable, setTablePagination } = useListStoreActions(); const cq = useContainerQuery(); const roles = useRoles({ @@ -369,7 +372,7 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF }, [filter, handleFilterChange, queryClient, server?.id]); const handleSetRole = useCallback( - (e: string | null) => { + (e: null | string) => { const updatedFilters = setFilter({ data: { role: e || '', @@ -403,10 +406,10 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF {FILTERS[server?.type as keyof typeof FILTERS].map((f) => ( {f.name} @@ -415,8 +418,8 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF {server?.type === ServerType.JELLYFIN && ( <> @@ -435,10 +438,10 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF {musicFoldersQuery.data?.items.map((folder) => ( {folder.name} @@ -452,18 +455,18 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF setStore({ genre: e || '' })} + value={genre} /> { setStore({ played: e as Played }); }} + value={played} /> )} @@ -210,18 +211,18 @@ export const ShuffleAllModal = ({ @@ -229,9 +230,9 @@ export const ShuffleAllModal = ({ diff --git a/src/renderer/features/player/components/visualizer.tsx b/src/renderer/features/player/components/visualizer.tsx index 3e633eec..e1405a51 100644 --- a/src/renderer/features/player/components/visualizer.tsx +++ b/src/renderer/features/player/components/visualizer.tsx @@ -1,7 +1,8 @@ -import { createRef, useCallback, useEffect, useState } from 'react'; -import { useWebAudio } from '/@/renderer/features/player/hooks/use-webaudio'; import AudioMotionAnalyzer from 'audiomotion-analyzer'; +import { createRef, useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; + +import { useWebAudio } from '/@/renderer/features/player/hooks/use-webaudio'; import { useSettingsStore } from '/@/renderer/store'; const StyledContainer = styled.div` diff --git a/src/renderer/features/player/context/play-queue-handler-context.ts b/src/renderer/features/player/context/play-queue-handler-context.ts index ae1d0265..dc45db08 100644 --- a/src/renderer/features/player/context/play-queue-handler-context.ts +++ b/src/renderer/features/player/context/play-queue-handler-context.ts @@ -1,4 +1,5 @@ import { createContext } from 'react'; + import { PlayQueueAddOptions } from '/@/renderer/types'; export const PlayQueueHandlerContext = createContext<{ diff --git a/src/renderer/features/player/context/webaudio-context.ts b/src/renderer/features/player/context/webaudio-context.ts index caabca8d..710cf933 100644 --- a/src/renderer/features/player/context/webaudio-context.ts +++ b/src/renderer/features/player/context/webaudio-context.ts @@ -1,4 +1,5 @@ import { createContext } from 'react'; + import { WebAudio } from '/@/renderer/types'; export const WebAudioContext = createContext<{ diff --git a/src/renderer/features/player/hooks/use-center-controls.ts b/src/renderer/features/player/hooks/use-center-controls.ts index ac34f0e8..b6f5f53f 100644 --- a/src/renderer/features/player/hooks/use-center-controls.ts +++ b/src/renderer/features/player/hooks/use-center-controls.ts @@ -1,6 +1,11 @@ -import { useCallback, useEffect } from 'react'; import isElectron from 'is-electron'; -import { PlaybackType, PlayerRepeat, PlayerShuffle, PlayerStatus } from '/@/renderer/types'; +import debounce from 'lodash/debounce'; +import { useCallback, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { toast } from '/@/renderer/components'; +import { useScrobble } from '/@/renderer/features/player/hooks/use-scrobble'; +import { updateSong } from '/@/renderer/features/player/update-remote-song'; import { useCurrentPlayer, useCurrentStatus, @@ -12,19 +17,15 @@ import { useShuffleStatus, } from '/@/renderer/store'; import { usePlaybackType } from '/@/renderer/store/settings.store'; -import { useScrobble } from '/@/renderer/features/player/hooks/use-scrobble'; -import debounce from 'lodash/debounce'; -import { toast } from '/@/renderer/components'; -import { useTranslation } from 'react-i18next'; -import { updateSong } from '/@/renderer/features/player/update-remote-song'; +import { PlaybackType, PlayerRepeat, PlayerShuffle, PlayerStatus } from '/@/renderer/types'; import { setAutoNext, setQueue, setQueueNext } from '/@/renderer/utils/set-transcoded-queue-data'; -const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null; -const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : null; -const ipc = isElectron() ? window.electron.ipc : null; -const utils = isElectron() ? window.electron.utils : null; -const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null; -const remote = isElectron() ? window.electron.remote : null; +const mpvPlayer = isElectron() ? window.api.mpvPlayer : null; +const mpvPlayerListener = isElectron() ? window.api.mpvPlayerListener : null; +const ipc = isElectron() ? window.api.ipc : null; +const utils = isElectron() ? window.api.utils : null; +const mpris = isElectron() && utils?.isLinux() ? window.api.mpris : null; +const remote = isElectron() ? window.api.remote : null; const mediaSession = navigator.mediaSession; export const useCenterControls = (args: { playersRef: any }) => { @@ -32,7 +33,7 @@ export const useCenterControls = (args: { playersRef: any }) => { const { playersRef } = args; const currentPlayer = useCurrentPlayer(); - const { setShuffle, setRepeat, play, pause, previous, next, setCurrentIndex, autoNext } = + const { autoNext, next, pause, play, previous, setCurrentIndex, setRepeat, setShuffle } = usePlayerControls(); const setCurrentTime = useSetCurrentTime(); const queue = useDefaultQueue(); @@ -45,7 +46,7 @@ export const useCenterControls = (args: { playersRef: any }) => { const currentPlayerRef = currentPlayer === 1 ? player1Ref : player2Ref; const nextPlayerRef = currentPlayer === 1 ? player2Ref : player1Ref; - const { handleScrobbleFromSongRestart, handleScrobbleFromSeek } = useScrobble(); + const { handleScrobbleFromSeek, handleScrobbleFromSongRestart } = useScrobble(); useEffect(() => { if (mediaSession) { @@ -226,12 +227,12 @@ export const useCenterControls = (args: { playersRef: any }) => { }; switch (repeatStatus) { - case PlayerRepeat.NONE: - handleRepeatNone[playbackType](); - break; case PlayerRepeat.ALL: handleRepeatAll[playbackType](); break; + case PlayerRepeat.NONE: + handleRepeatNone[playbackType](); + break; case PlayerRepeat.ONE: handleRepeatOne[playbackType](); break; @@ -310,12 +311,12 @@ export const useCenterControls = (args: { playersRef: any }) => { }; switch (repeatStatus) { - case PlayerRepeat.NONE: - handleRepeatNone[playbackType](); - break; case PlayerRepeat.ALL: handleRepeatAll[playbackType](); break; + case PlayerRepeat.NONE: + handleRepeatNone[playbackType](); + break; case PlayerRepeat.ONE: handleRepeatOne[playbackType](); break; @@ -418,12 +419,12 @@ export const useCenterControls = (args: { playersRef: any }) => { }; switch (repeatStatus) { - case PlayerRepeat.NONE: - handleRepeatNone[playbackType](); - break; case PlayerRepeat.ALL: handleRepeatAll[playbackType](); break; + case PlayerRepeat.NONE: + handleRepeatNone[playbackType](); + break; case PlayerRepeat.ONE: handleRepeatOne[playbackType](); break; @@ -510,7 +511,7 @@ export const useCenterControls = (args: { playersRef: any }) => { }, 100); const handleSeekSlider = useCallback( - (e: number | any) => { + (e: any | number) => { setCurrentTime(e, true); handleScrobbleFromSeek(e); debouncedSeek(e); @@ -564,6 +565,7 @@ export const useCenterControls = (args: { playersRef: any }) => { }); mpvPlayerListener.rendererCurrentTime((_event: any, time: number) => { + console.log('time :>> ', time); setCurrentTime(time); }); diff --git a/src/renderer/features/player/hooks/use-handle-playqueue-add.ts b/src/renderer/features/player/hooks/use-handle-playqueue-add.ts index b25f9e8c..f19cd4d4 100644 --- a/src/renderer/features/player/hooks/use-handle-playqueue-add.ts +++ b/src/renderer/features/player/hooks/use-handle-playqueue-add.ts @@ -1,31 +1,32 @@ -import { useCallback, useRef } from 'react'; import { useQueryClient } from '@tanstack/react-query'; -import { useCurrentServer, usePlayerControls, usePlayerStore } from '/@/renderer/store'; -import { useGeneralSettings, usePlaybackType } from '/@/renderer/store/settings.store'; -import { PlayQueueAddOptions, Play, PlaybackType } from '/@/renderer/types'; -import { toast } from '/@/renderer/components/toast/index'; import isElectron from 'is-electron'; import { nanoid } from 'nanoid/non-secure'; +import { useCallback, useRef } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { queryKeys } from '/@/renderer/api/query-keys'; import { + instanceOfCancellationError, LibraryItem, QueueSong, Song, SongListResponse, - instanceOfCancellationError, } from '/@/renderer/api/types'; -import { - getPlaylistSongsById, - getSongById, - getAlbumSongsById, - getAlbumArtistSongsById, - getSongsByQuery, - getGenreSongsById, - getArtistSongsById, -} from '/@/renderer/features/player/utils'; -import { queryKeys } from '/@/renderer/api/query-keys'; -import { useTranslation } from 'react-i18next'; +import { toast } from '/@/renderer/components/toast/index'; import { PlayersRef } from '/@/renderer/features/player/ref/players-ref'; import { updateSong } from '/@/renderer/features/player/update-remote-song'; +import { + getAlbumArtistSongsById, + getAlbumSongsById, + getArtistSongsById, + getGenreSongsById, + getPlaylistSongsById, + getSongById, + getSongsByQuery, +} from '/@/renderer/features/player/utils'; +import { useCurrentServer, usePlayerControls, usePlayerStore } from '/@/renderer/store'; +import { useGeneralSettings, usePlaybackType } from '/@/renderer/store/settings.store'; +import { Play, PlaybackType, PlayQueueAddOptions } from '/@/renderer/types'; import { setQueue, setQueueNext } from '/@/renderer/utils/set-transcoded-queue-data'; const getRootQueryKey = (itemType: LibraryItem, serverId: string) => { @@ -55,7 +56,7 @@ const getRootQueryKey = (itemType: LibraryItem, serverId: string) => { return queryKey; }; -const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null; +const mpvPlayer = isElectron() ? window.api.mpvPlayer : null; const addToQueue = usePlayerStore.getState().actions.addToQueue; @@ -65,20 +66,20 @@ export const useHandlePlayQueueAdd = () => { const playbackType = usePlaybackType(); const server = useCurrentServer(); const { play } = usePlayerControls(); - const timeoutIds = useRef> | null>({}); + const timeoutIds = useRef>>({}); const { doubleClickQueueAll } = useGeneralSettings(); const handlePlayQueueAdd = useCallback( async (options: PlayQueueAddOptions) => { if (!server) return toast.error({ message: 'No server selected', type: 'error' }); - const { initialIndex, initialSongId, playType, byData, byItemType, query } = options; - let songs: QueueSong[] | null = null; + const { byData, byItemType, initialIndex, initialSongId, playType, query } = options; + let songs: null | QueueSong[] = null; let initialSongIndex = 0; if (byItemType) { let songList: SongListResponse | undefined; - const { type: itemType, id } = byItemType; + const { id, type: itemType } = byItemType; const fetchId = nanoid(); timeoutIds.current = { diff --git a/src/renderer/features/player/hooks/use-playqueue-add.ts b/src/renderer/features/player/hooks/use-playqueue-add.ts index 4703cb61..bfda2a7b 100644 --- a/src/renderer/features/player/hooks/use-playqueue-add.ts +++ b/src/renderer/features/player/hooks/use-playqueue-add.ts @@ -1,4 +1,5 @@ import { useContext } from 'react'; + import { PlayQueueHandlerContext } from '/@/renderer/features/player/context/play-queue-handler-context'; export const usePlayQueueAdd = () => { diff --git a/src/renderer/features/player/hooks/use-right-controls.ts b/src/renderer/features/player/hooks/use-right-controls.ts index eac4e805..526291ca 100644 --- a/src/renderer/features/player/hooks/use-right-controls.ts +++ b/src/renderer/features/player/hooks/use-right-controls.ts @@ -1,5 +1,6 @@ -import { useCallback, useEffect, WheelEvent } from 'react'; import isElectron from 'is-electron'; +import { useCallback, useEffect, WheelEvent } from 'react'; + import { useMuted, usePlayerControls, @@ -9,10 +10,10 @@ import { } from '/@/renderer/store'; import { useGeneralSettings } from '/@/renderer/store/settings.store'; -const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null; -const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : null; -const ipc = isElectron() ? window.electron.ipc : null; -const remote = isElectron() ? window.electron.remote : null; +const mpvPlayer = isElectron() ? window.api.mpvPlayer : null; +const mpvPlayerListener = isElectron() ? window.api.mpvPlayerListener : null; +const ipc = isElectron() ? window.api.ipc : null; +const remote = isElectron() ? window.api.remote : null; const calculateVolumeUp = (volume: number, volumeWheelStep: number) => { let volumeToSet; @@ -39,7 +40,7 @@ const calculateVolumeDown = (volume: number, volumeWheelStep: number) => { }; export const useRightControls = () => { - const { setVolume, setMuted } = usePlayerControls(); + const { setMuted, setVolume } = usePlayerControls(); const volume = useVolume(); const muted = useMuted(); const { volumeWheelStep } = useGeneralSettings(); @@ -98,7 +99,7 @@ export const useRightControls = () => { }, [setVolume, volume, volumeWheelStep]); const handleVolumeWheel = useCallback( - (e: WheelEvent) => { + (e: WheelEvent) => { let volumeToSet; if (e.deltaY > 0 || e.deltaX > 0) { volumeToSet = calculateVolumeDown(volume, volumeWheelStep); diff --git a/src/renderer/features/player/hooks/use-scrobble.ts b/src/renderer/features/player/hooks/use-scrobble.ts index fc9a833b..281c78d1 100644 --- a/src/renderer/features/player/hooks/use-scrobble.ts +++ b/src/renderer/features/player/hooks/use-scrobble.ts @@ -1,4 +1,5 @@ -import { useEffect, useCallback, useState, useRef } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; + import { QueueSong, ServerType } from '/@/renderer/api/types'; import { useSendScrobble } from '/@/renderer/features/player/mutations/scrobble-mutation'; import { usePlayerStore } from '/@/renderer/store'; @@ -82,12 +83,12 @@ export const useScrobble = () => { [isScrobbleEnabled, sendScrobble], ); - const progressIntervalId = useRef | null>(null); - const songChangeTimeoutId = useRef | null>(null); + const progressIntervalId = useRef>(null); + const songChangeTimeoutId = useRef>(null); const handleScrobbleFromSongChange = useCallback( ( - current: (QueueSong | number | undefined)[], - previous: (QueueSong | number | undefined)[], + current: (number | QueueSong | undefined)[], + previous: (number | QueueSong | undefined)[], ) => { if (!isScrobbleEnabled) return; @@ -179,8 +180,8 @@ export const useScrobble = () => { const handleScrobbleFromStatusChange = useCallback( ( - current: (PlayerStatus | number | undefined)[], - previous: (PlayerStatus | number | undefined)[], + current: (number | PlayerStatus | undefined)[], + previous: (number | PlayerStatus | undefined)[], ) => { if (!isScrobbleEnabled) return; diff --git a/src/renderer/features/player/hooks/use-webaudio.ts b/src/renderer/features/player/hooks/use-webaudio.ts index 5b8bc334..209e732f 100644 --- a/src/renderer/features/player/hooks/use-webaudio.ts +++ b/src/renderer/features/player/hooks/use-webaudio.ts @@ -1,7 +1,8 @@ import { useContext } from 'react'; + import { WebAudioContext } from '/@/renderer/features/player/context/webaudio-context'; export const useWebAudio = () => { - const { webAudio, setWebAudio } = useContext(WebAudioContext); + const { setWebAudio, webAudio } = useContext(WebAudioContext); return { setWebAudio, webAudio }; }; diff --git a/src/renderer/features/player/mutations/scrobble-mutation.ts b/src/renderer/features/player/mutations/scrobble-mutation.ts index 8b1688d1..7445fb07 100644 --- a/src/renderer/features/player/mutations/scrobble-mutation.ts +++ b/src/renderer/features/player/mutations/scrobble-mutation.ts @@ -1,7 +1,8 @@ import { useMutation } from '@tanstack/react-query'; import { AxiosError } from 'axios'; + import { api } from '/@/renderer/api'; -import { ScrobbleResponse, ScrobbleArgs } from '/@/renderer/api/types'; +import { ScrobbleArgs, ScrobbleResponse } from '/@/renderer/api/types'; import { MutationOptions } from '/@/renderer/lib/react-query'; import { getServerById, useIncrementQueuePlayCount } from '/@/renderer/store'; import { usePlayEvent } from '/@/renderer/store/event.store'; @@ -13,7 +14,7 @@ export const useSendScrobble = (options?: MutationOptions) => { return useMutation< ScrobbleResponse, AxiosError, - Omit, + Omit, null >({ mutationFn: (args) => { diff --git a/src/renderer/features/player/update-remote-song.tsx b/src/renderer/features/player/update-remote-song.tsx index 1941e60e..a091068d 100644 --- a/src/renderer/features/player/update-remote-song.tsx +++ b/src/renderer/features/player/update-remote-song.tsx @@ -1,7 +1,8 @@ import isElectron from 'is-electron'; + import { QueueSong } from '/@/renderer/api/types'; -const remote = isElectron() ? window.electron.remote : null; +const remote = isElectron() ? window.api.remote : null; const mediaSession = navigator.mediaSession; export const updateSong = (song: QueueSong | undefined) => { diff --git a/src/renderer/features/player/utils.ts b/src/renderer/features/player/utils.ts index 6fa6a312..c0f2b284 100644 --- a/src/renderer/features/player/utils.ts +++ b/src/renderer/features/player/utils.ts @@ -1,14 +1,15 @@ import { QueryClient } from '@tanstack/react-query'; + import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { PlaylistSongListQuery, + ServerListItem, SongDetailQuery, SongListQuery, SongListResponse, SongListSort, SortOrder, - ServerListItem, } from '/@/renderer/api/types'; export const getPlaylistSongsById = async (args: { @@ -17,7 +18,7 @@ export const getPlaylistSongsById = async (args: { queryClient: QueryClient; server: ServerListItem; }) => { - const { id, queryClient, server, query } = args; + const { id, query, queryClient, server } = args; const queryFilter: PlaylistSongListQuery = { id, @@ -55,7 +56,7 @@ export const getAlbumSongsById = async (args: { queryClient: QueryClient; server: ServerListItem; }) => { - const { id, queryClient, server, query } = args; + const { id, query, queryClient, server } = args; const queryFilter: SongListQuery = { albumIds: id, @@ -91,9 +92,9 @@ export const getGenreSongsById = async (args: { orderByIds?: boolean; query?: Partial; queryClient: QueryClient; - server: ServerListItem | null; + server: null | ServerListItem; }) => { - const { id, queryClient, server, query } = args; + const { id, query, queryClient, server } = args; const data: SongListResponse = { items: [], @@ -143,7 +144,7 @@ export const getAlbumArtistSongsById = async (args: { queryClient: QueryClient; server: ServerListItem; }) => { - const { id, queryClient, server, query } = args; + const { id, query, queryClient, server } = args; const queryFilter: SongListQuery = { albumArtistIds: id || [], @@ -180,7 +181,7 @@ export const getArtistSongsById = async (args: { queryClient: QueryClient; server: ServerListItem; }) => { - const { id, queryClient, server, query } = args; + const { id, query, queryClient, server } = args; const queryFilter: SongListQuery = { artistIds: id, @@ -216,7 +217,7 @@ export const getSongsByQuery = async (args: { queryClient: QueryClient; server: ServerListItem; }) => { - const { queryClient, server, query } = args; + const { query, queryClient, server } = args; const queryFilter: SongListQuery = { sortBy: SongListSort.ALBUM, diff --git a/src/renderer/features/playlists/components/add-to-playlist-context-modal.tsx b/src/renderer/features/playlists/components/add-to-playlist-context-modal.tsx index c20c76ac..9fddb545 100644 --- a/src/renderer/features/playlists/components/add-to-playlist-context-modal.tsx +++ b/src/renderer/features/playlists/components/add-to-playlist-context-modal.tsx @@ -1,7 +1,9 @@ -import { useMemo, useState } from 'react'; import { Box, Group, Stack } from '@mantine/core'; import { useForm } from '@mantine/form'; import { closeModal, ContextModalProps } from '@mantine/modals'; +import { useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; + import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { PlaylistListSort, SongListQuery, SongListSort, SortOrder } from '/@/renderer/api/types'; @@ -11,7 +13,6 @@ import { useAddToPlaylist } from '/@/renderer/features/playlists/mutations/add-t import { usePlaylistList } from '/@/renderer/features/playlists/queries/playlist-list-query'; import { queryClient } from '/@/renderer/lib/react-query'; import { useCurrentServer } from '/@/renderer/store'; -import { useTranslation } from 'react-i18next'; export const AddToPlaylistContextModal = ({ id, @@ -217,13 +218,13 @@ export const AddToPlaylistContextModal = ({ @@ -238,9 +239,9 @@ export const AddToPlaylistContextModal = ({ diff --git a/src/renderer/features/playlists/components/create-playlist-form.tsx b/src/renderer/features/playlists/components/create-playlist-form.tsx index 13f8609b..fbd3a3ae 100644 --- a/src/renderer/features/playlists/components/create-playlist-form.tsx +++ b/src/renderer/features/playlists/components/create-playlist-form.tsx @@ -1,7 +1,11 @@ -import { useRef, useState } from 'react'; import { Group, Stack } from '@mantine/core'; import { useForm } from '@mantine/form'; +import { useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { ServerFeature } from '/@/renderer/api/features-types'; import { CreatePlaylistBody, ServerType, SongListSort } from '/@/renderer/api/types'; +import { hasFeature } from '/@/renderer/api/utils'; import { Button, Switch, Text, TextInput, toast } from '/@/renderer/components'; import { PlaylistQueryBuilder, @@ -10,9 +14,6 @@ import { import { useCreatePlaylist } from '/@/renderer/features/playlists/mutations/create-playlist-mutation'; import { convertQueryGroupToNDQuery } from '/@/renderer/features/playlists/utils'; import { useCurrentServer } from '/@/renderer/store'; -import { useTranslation } from 'react-i18next'; -import { hasFeature } from '/@/renderer/api/utils'; -import { ServerFeature } from '/@/renderer/api/features-types'; interface CreatePlaylistFormProps { onCancel: () => void; @@ -95,11 +96,11 @@ export const CreatePlaylistForm = ({ onCancel }: CreatePlaylistFormProps) => { {server?.type === ServerType.NAVIDROME && ( @@ -135,10 +136,10 @@ export const CreatePlaylistForm = ({ onCancel }: CreatePlaylistFormProps) => { Query Editor @@ -147,8 +148,8 @@ export const CreatePlaylistForm = ({ onCancel }: CreatePlaylistFormProps) => { diff --git a/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx b/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx index 445cde53..9d39dbd8 100644 --- a/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx +++ b/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx @@ -8,11 +8,13 @@ import type { RowDragEvent, } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + import { useQueryClient } from '@tanstack/react-query'; import { AnimatePresence } from 'framer-motion'; import debounce from 'lodash/debounce'; import { MutableRefObject, useCallback, useMemo } from 'react'; import { useParams } from 'react-router'; + import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { @@ -23,8 +25,9 @@ import { SongListSort, SortOrder, } from '/@/renderer/api/types'; +import { toast } from '/@/renderer/components'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; -import { TablePagination, VirtualTable, getColumnDefs } from '/@/renderer/components/virtual-table'; +import { getColumnDefs, TablePagination, VirtualTable } from '/@/renderer/components/virtual-table'; import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; import { useHandleTableContextMenu } from '/@/renderer/features/context-menu'; import { @@ -34,6 +37,7 @@ import { import { usePlayQueueAdd } from '/@/renderer/features/player'; import { usePlaylistDetail } from '/@/renderer/features/playlists/queries/playlist-detail-query'; import { usePlaylistSongList } from '/@/renderer/features/playlists/queries/playlist-song-list-query'; +import { useAppFocus } from '/@/renderer/hooks'; import { useCurrentServer, useCurrentSong, @@ -45,8 +49,6 @@ import { } from '/@/renderer/store'; import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; import { ListDisplayType, ServerType } from '/@/renderer/types'; -import { useAppFocus } from '/@/renderer/hooks'; -import { toast } from '/@/renderer/components'; interface PlaylistDetailContentProps { songs?: Song[]; @@ -290,12 +292,7 @@ export const PlaylistDetailSongListContent = ({ songs, tableRef }: PlaylistDetai <> {isPaginationEnabled && ( {page.display === ListDisplayType.TABLE_PAGINATED && ( { const { t } = useTranslation(); const { playlistId } = useParams() as { playlistId: string }; @@ -493,10 +495,10 @@ export const PlaylistDetailSongListHeaderFilters = ({ {FILTERS[server?.type as keyof typeof FILTERS].map((filter) => ( {filter.name} @@ -506,8 +508,8 @@ export const PlaylistDetailSongListHeaderFilters = ({ @@ -601,8 +603,8 @@ export const PlaylistDetailSongListHeaderFilters = ({ Table @@ -642,8 +644,8 @@ export const PlaylistDetailSongListHeaderFilters = ({ defaultValue={page.table?.columns.map( (column) => column.column, )} - width={300} onChange={handleTableColumns} + width={300} /> Auto Fit Columns diff --git a/src/renderer/features/playlists/components/playlist-detail-song-list-header.tsx b/src/renderer/features/playlists/components/playlist-detail-song-list-header.tsx index 29e7a51e..ae28ef50 100644 --- a/src/renderer/features/playlists/components/playlist-detail-song-list-header.tsx +++ b/src/renderer/features/playlists/components/playlist-detail-song-list-header.tsx @@ -1,8 +1,10 @@ -import { MutableRefObject } from 'react'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + import { Stack } from '@mantine/core'; +import { MutableRefObject } from 'react'; import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router'; + import { LibraryItem } from '/@/renderer/api/types'; import { Badge, PageHeader, Paper, SpinnerIcon } from '/@/renderer/components'; import { usePlayQueueAdd } from '/@/renderer/features/player'; @@ -20,9 +22,9 @@ interface PlaylistDetailHeaderProps { } export const PlaylistDetailSongListHeader = ({ - tableRef, - itemCount, handleToggleShowQueryBuilder, + itemCount, + tableRef, }: PlaylistDetailHeaderProps) => { const { t } = useTranslation(); const { playlistId } = useParams() as { playlistId: string }; diff --git a/src/renderer/features/playlists/components/playlist-list-content.tsx b/src/renderer/features/playlists/components/playlist-list-content.tsx index ed40b04d..61427068 100644 --- a/src/renderer/features/playlists/components/playlist-list-content.tsx +++ b/src/renderer/features/playlists/components/playlist-list-content.tsx @@ -1,10 +1,13 @@ -import { lazy, MutableRefObject, Suspense } from 'react'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + +import { lazy, MutableRefObject, Suspense } from 'react'; + +import { useListContext } from '../../../context/list-context'; +import { useListStoreByKey } from '../../../store/list.store'; + import { Spinner } from '/@/renderer/components'; import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid'; import { ListDisplayType } from '/@/renderer/types'; -import { useListContext } from '../../../context/list-context'; -import { useListStoreByKey } from '../../../store/list.store'; const PlaylistListTableView = lazy(() => import('/@/renderer/features/playlists/components/playlist-list-table-view').then((module) => ({ @@ -19,12 +22,12 @@ const PlaylistListGridView = lazy(() => ); interface PlaylistListContentProps { - gridRef: MutableRefObject; + gridRef: MutableRefObject; itemCount?: number; tableRef: MutableRefObject; } -export const PlaylistListContent = ({ gridRef, tableRef, itemCount }: PlaylistListContentProps) => { +export const PlaylistListContent = ({ gridRef, itemCount, tableRef }: PlaylistListContentProps) => { const { pageKey } = useListContext(); const { display } = useListStoreByKey({ key: pageKey }); diff --git a/src/renderer/features/playlists/components/playlist-list-grid-view.tsx b/src/renderer/features/playlists/components/playlist-list-grid-view.tsx index 9dad4a9e..3038f1d8 100644 --- a/src/renderer/features/playlists/components/playlist-list-grid-view.tsx +++ b/src/renderer/features/playlists/components/playlist-list-grid-view.tsx @@ -2,8 +2,10 @@ import { QueryKey, useQueryClient } from '@tanstack/react-query'; import { MutableRefObject, useCallback, useMemo } from 'react'; import AutoSizer, { Size } from 'react-virtualized-auto-sizer'; import { ListOnScrollProps } from 'react-window'; + import { useListContext } from '../../../context/list-context'; import { useListStoreActions } from '../../../store/list.store'; + import { controller } from '/@/renderer/api/controller'; import { queryKeys } from '/@/renderer/api/query-keys'; import { @@ -20,13 +22,13 @@ import { VirtualInfiniteGridRef, } from '/@/renderer/components/virtual-grid'; import { usePlayQueueAdd } from '/@/renderer/features/player'; +import { useHandleFavorite } from '/@/renderer/features/shared/hooks/use-handle-favorite'; import { AppRoute } from '/@/renderer/router/routes'; import { useCurrentServer, useListStoreByKey } from '/@/renderer/store'; import { CardRow, ListDisplayType } from '/@/renderer/types'; -import { useHandleFavorite } from '/@/renderer/features/shared/hooks/use-handle-favorite'; interface PlaylistListGridViewProps { - gridRef: MutableRefObject; + gridRef: MutableRefObject; itemCount?: number; } @@ -35,7 +37,7 @@ export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridVie const queryClient = useQueryClient(); const server = useCurrentServer(); const handlePlayQueueAdd = usePlayQueueAdd(); - const { display, grid, filter } = useListStoreByKey({ key: pageKey }); + const { display, filter, grid } = useListStoreByKey({ key: pageKey }); const { setGrid } = useListStoreActions(); const handleFavorite = useHandleFavorite({ gridRef, server }); @@ -49,15 +51,15 @@ export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridVie case PlaylistListSort.NAME: rows.push(PLAYLIST_CARD_ROWS.songCount); break; - case PlaylistListSort.SONG_COUNT: - rows.push(PLAYLIST_CARD_ROWS.songCount); - break; case PlaylistListSort.OWNER: rows.push(PLAYLIST_CARD_ROWS.owner); break; case PlaylistListSort.PUBLIC: rows.push(PLAYLIST_CARD_ROWS.public); break; + case PlaylistListSort.SONG_COUNT: + rows.push(PLAYLIST_CARD_ROWS.songCount); + break; case PlaylistListSort.UPDATED_AT: break; } @@ -73,7 +75,7 @@ export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridVie ); const fetchInitialData = useCallback(() => { - const query: Omit = { + const query: Omit = { ...filter, }; @@ -140,8 +142,6 @@ export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridVie {({ height, width }: Size) => ( )} diff --git a/src/renderer/features/playlists/components/playlist-list-header-filters.tsx b/src/renderer/features/playlists/components/playlist-list-header-filters.tsx index 771dd592..5a44e87b 100644 --- a/src/renderer/features/playlists/components/playlist-list-header-filters.tsx +++ b/src/renderer/features/playlists/components/playlist-list-header-filters.tsx @@ -1,12 +1,16 @@ -import { ChangeEvent, MouseEvent, MutableRefObject, useCallback } from 'react'; -import { IDatasource } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + +import { IDatasource } from '@ag-grid-community/core'; import { Divider, Flex, Group, Stack } from '@mantine/core'; import { useQueryClient } from '@tanstack/react-query'; +import { ChangeEvent, MouseEvent, MutableRefObject, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { RiMoreFill, RiRefreshLine, RiSettings3Fill } from 'react-icons/ri'; + import { useListContext } from '../../../context/list-context'; import { useListStoreByKey } from '../../../store/list.store'; + +import i18n from '/@/i18n/i18n'; import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { LibraryItem, PlaylistListQuery, PlaylistListSort, SortOrder } from '/@/renderer/api/types'; @@ -17,7 +21,6 @@ import { OrderToggleButton } from '/@/renderer/features/shared'; import { useContainerQuery } from '/@/renderer/hooks'; import { PlaylistListFilter, useCurrentServer, useListStoreActions } from '/@/renderer/store'; import { ListDisplayType, TableColumn } from '/@/renderer/types'; -import i18n from '/@/i18n/i18n'; const FILTERS = { jellyfin: [ @@ -104,7 +107,7 @@ const FILTERS = { }; interface PlaylistListHeaderFiltersProps { - gridRef: MutableRefObject; + gridRef: MutableRefObject; tableRef: MutableRefObject; } @@ -116,9 +119,9 @@ export const PlaylistListHeaderFilters = ({ const { pageKey } = useListContext(); const queryClient = useQueryClient(); const server = useCurrentServer(); - const { setFilter, setTable, setTablePagination, setGrid, setDisplayType } = + const { setDisplayType, setFilter, setGrid, setTable, setTablePagination } = useListStoreActions(); - const { display, filter, table, grid } = useListStoreByKey({ key: pageKey }); + const { display, filter, grid, table } = useListStoreByKey({ key: pageKey }); const cq = useContainerQuery(); const isGrid = display === ListDisplayType.CARD || display === ListDisplayType.POSTER; @@ -337,10 +340,10 @@ export const PlaylistListHeaderFilters = ({ {FILTERS[server?.type as keyof typeof FILTERS].map((f) => ( {f.name} @@ -349,16 +352,16 @@ export const PlaylistListHeaderFilters = ({ @@ -404,22 +407,22 @@ export const PlaylistListHeaderFilters = ({ {t('table.config.view.card', { postProcess: 'titleCase' })} {t('table.config.view.poster', { postProcess: 'titleCase' })} {t('table.config.view.table', { postProcess: 'titleCase' })} @@ -478,8 +481,8 @@ export const PlaylistListHeaderFilters = ({ defaultValue={table?.columns.map( (column) => column.column, )} - width={300} onChange={handleTableColumns} + width={300} /> diff --git a/src/renderer/features/playlists/components/playlist-list-header.tsx b/src/renderer/features/playlists/components/playlist-list-header.tsx index ccb57dd6..b9cccbed 100644 --- a/src/renderer/features/playlists/components/playlist-list-header.tsx +++ b/src/renderer/features/playlists/components/playlist-list-header.tsx @@ -1,27 +1,29 @@ -import { ChangeEvent, MutableRefObject } from 'react'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + import { Flex, Group, Stack } from '@mantine/core'; -import { openModal, closeAllModals } from '@mantine/modals'; -import { PageHeader, SpinnerIcon, Paper, Button, SearchInput } from '/@/renderer/components'; +import { closeAllModals, openModal } from '@mantine/modals'; +import debounce from 'lodash/debounce'; +import { ChangeEvent, MutableRefObject } from 'react'; +import { useTranslation } from 'react-i18next'; +import { RiFileAddFill } from 'react-icons/ri'; + +import { LibraryItem, PlaylistListQuery, ServerType } from '/@/renderer/api/types'; +import { Button, PageHeader, Paper, SearchInput, SpinnerIcon } from '/@/renderer/components'; import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid'; import { CreatePlaylistForm } from '/@/renderer/features/playlists/components/create-playlist-form'; import { PlaylistListHeaderFilters } from '/@/renderer/features/playlists/components/playlist-list-header-filters'; import { LibraryHeaderBar } from '/@/renderer/features/shared'; import { useContainerQuery } from '/@/renderer/hooks'; -import { PlaylistListFilter, useCurrentServer } from '/@/renderer/store'; -import debounce from 'lodash/debounce'; -import { useTranslation } from 'react-i18next'; -import { RiFileAddFill } from 'react-icons/ri'; -import { LibraryItem, PlaylistListQuery, ServerType } from '/@/renderer/api/types'; import { useDisplayRefresh } from '/@/renderer/hooks/use-display-refresh'; +import { PlaylistListFilter, useCurrentServer } from '/@/renderer/store'; interface PlaylistListHeaderProps { - gridRef: MutableRefObject; + gridRef: MutableRefObject; itemCount?: number; tableRef: MutableRefObject; } -export const PlaylistListHeader = ({ itemCount, tableRef, gridRef }: PlaylistListHeaderProps) => { +export const PlaylistListHeader = ({ gridRef, itemCount, tableRef }: PlaylistListHeaderProps) => { const { t } = useTranslation(); const cq = useContainerQuery(); const server = useCurrentServer(); @@ -78,12 +80,12 @@ export const PlaylistListHeader = ({ itemCount, tableRef, gridRef }: PlaylistLis )} @@ -91,8 +93,8 @@ export const PlaylistListHeader = ({ itemCount, tableRef, gridRef }: PlaylistLis diff --git a/src/renderer/features/playlists/components/playlist-list-table-view.tsx b/src/renderer/features/playlists/components/playlist-list-table-view.tsx index af5fe0e3..744b58ca 100644 --- a/src/renderer/features/playlists/components/playlist-list-table-view.tsx +++ b/src/renderer/features/playlists/components/playlist-list-table-view.tsx @@ -1,7 +1,9 @@ -import { MutableRefObject } from 'react'; -import { RowDoubleClickedEvent } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + +import { RowDoubleClickedEvent } from '@ag-grid-community/core'; +import { MutableRefObject } from 'react'; import { generatePath, useNavigate } from 'react-router'; + import { LibraryItem } from '/@/renderer/api/types'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; import { VirtualTable } from '/@/renderer/components/virtual-table'; @@ -15,7 +17,7 @@ interface PlaylistListTableViewProps { tableRef: MutableRefObject; } -export const PlaylistListTableView = ({ tableRef, itemCount }: PlaylistListTableViewProps) => { +export const PlaylistListTableView = ({ itemCount, tableRef }: PlaylistListTableViewProps) => { const navigate = useNavigate(); const server = useCurrentServer(); const pageKey = 'playlist'; diff --git a/src/renderer/features/playlists/components/playlist-query-builder.tsx b/src/renderer/features/playlists/components/playlist-query-builder.tsx index dde8c42d..82bda953 100644 --- a/src/renderer/features/playlists/components/playlist-query-builder.tsx +++ b/src/renderer/features/playlists/components/playlist-query-builder.tsx @@ -1,4 +1,3 @@ -import { forwardRef, Ref, useImperativeHandle, useMemo, useState } from 'react'; import { Group } from '@mantine/core'; import { useForm } from '@mantine/form'; import { openModal } from '@mantine/modals'; @@ -6,6 +5,19 @@ import clone from 'lodash/clone'; import get from 'lodash/get'; import setWith from 'lodash/setWith'; import { nanoid } from 'nanoid'; +import { forwardRef, Ref, useImperativeHandle, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { RiMore2Fill, RiSaveLine } from 'react-icons/ri'; + +import { + NDSongQueryBooleanOperators, + NDSongQueryDateOperators, + NDSongQueryFields, + NDSongQueryNumberOperators, + NDSongQueryPlaylistOperators, + NDSongQueryStringOperators, +} from '/@/renderer/api/navidrome.types'; +import { PlaylistListSort, SongListSort, SortOrder } from '/@/renderer/api/types'; import { Button, DropdownMenu, @@ -15,25 +27,14 @@ import { ScrollArea, Select, } from '/@/renderer/components'; +import { usePlaylistList } from '/@/renderer/features/playlists/queries/playlist-list-query'; import { convertNDQueryToQueryGroup, convertQueryGroupToNDQuery, } from '/@/renderer/features/playlists/utils'; -import { QueryBuilderGroup, QueryBuilderRule } from '/@/renderer/types'; -import { useTranslation } from 'react-i18next'; -import { RiMore2Fill, RiSaveLine } from 'react-icons/ri'; -import { PlaylistListSort, SongListSort, SortOrder } from '/@/renderer/api/types'; -import { - NDSongQueryBooleanOperators, - NDSongQueryDateOperators, - NDSongQueryFields, - NDSongQueryNumberOperators, - NDSongQueryPlaylistOperators, - NDSongQueryStringOperators, -} from '/@/renderer/api/navidrome.types'; -import { usePlaylistList } from '/@/renderer/features/playlists/queries/playlist-list-query'; -import { useCurrentServer } from '/@/renderer/store'; import { JsonPreview } from '/@/renderer/features/shared/components/json-preview'; +import { useCurrentServer } from '/@/renderer/store'; +import { QueryBuilderGroup, QueryBuilderRule } from '/@/renderer/types'; type AddArgs = { groupIndex: number[]; @@ -91,14 +92,14 @@ export type PlaylistQueryBuilderRef = { export const PlaylistQueryBuilder = forwardRef( ( { - sortOrder, - sortBy, - limit, isSaving, - query, + limit, onSave, onSaveAs, playlistId, + query, + sortBy, + sortOrder, }: PlaylistQueryBuilderProps, ref: Ref, ) => { @@ -177,7 +178,7 @@ export const PlaylistQueryBuilder = forwardRef( }; const handleAddRuleGroup = (args: AddArgs) => { - const { level, groupIndex } = args; + const { groupIndex, level } = args; const filtersCopy = clone(filters); const getPath = (level: number) => { @@ -218,7 +219,7 @@ export const PlaylistQueryBuilder = forwardRef( }; const handleDeleteRuleGroup = (args: DeleteArgs) => { - const { uniqueId, level, groupIndex } = args; + const { groupIndex, level, uniqueId } = args; const filtersCopy = clone(filters); const getPath = (level: number) => { @@ -264,7 +265,7 @@ export const PlaylistQueryBuilder = forwardRef( }; const handleAddRule = (args: AddArgs) => { - const { level, groupIndex } = args; + const { groupIndex, level } = args; const filtersCopy = clone(filters); const path = getRulePath(level, groupIndex); @@ -287,7 +288,7 @@ export const PlaylistQueryBuilder = forwardRef( }; const handleDeleteRule = (args: DeleteArgs) => { - const { uniqueId, level, groupIndex } = args; + const { groupIndex, level, uniqueId } = args; const filtersCopy = clone(filters); const path = getRulePath(level, groupIndex); @@ -304,7 +305,7 @@ export const PlaylistQueryBuilder = forwardRef( }; const handleChangeField = (args: any) => { - const { uniqueId, level, groupIndex, value } = args; + const { groupIndex, level, uniqueId, value } = args; const filtersCopy = clone(filters); const path = getRulePath(level, groupIndex); @@ -327,7 +328,7 @@ export const PlaylistQueryBuilder = forwardRef( }; const handleChangeType = (args: any) => { - const { level, groupIndex, value } = args; + const { groupIndex, level, value } = args; const filtersCopy = clone(filters); @@ -359,7 +360,7 @@ export const PlaylistQueryBuilder = forwardRef( }; const handleChangeOperator = (args: any) => { - const { uniqueId, level, groupIndex, value } = args; + const { groupIndex, level, uniqueId, value } = args; const filtersCopy = clone(filters); const path = getRulePath(level, groupIndex); @@ -380,7 +381,7 @@ export const PlaylistQueryBuilder = forwardRef( }; const handleChangeValue = (args: any) => { - const { uniqueId, level, groupIndex, value } = args; + const { groupIndex, level, uniqueId, value } = args; const filtersCopy = clone(filters); const path = getRulePath(level, groupIndex); @@ -424,15 +425,6 @@ export const PlaylistQueryBuilder = forwardRef( filters={NDSongQueryFields} groupIndex={[]} level={0} - operators={{ - boolean: NDSongQueryBooleanOperators, - date: NDSongQueryDateOperators, - number: NDSongQueryNumberOperators, - playlist: NDSongQueryPlaylistOperators, - string: NDSongQueryStringOperators, - }} - playlists={playlistData} - uniqueId={filters.uniqueId} onAddRule={handleAddRule} onAddRuleGroup={handleAddRuleGroup} onChangeField={handleChangeField} @@ -443,12 +435,21 @@ export const PlaylistQueryBuilder = forwardRef( onDeleteRule={handleDeleteRule} onDeleteRuleGroup={handleDeleteRuleGroup} onResetFilters={handleResetFilters} + operators={{ + boolean: NDSongQueryBooleanOperators, + date: NDSongQueryDateOperators, + number: NDSongQueryNumberOperators, + playlist: NDSongQueryPlaylistOperators, + string: NDSongQueryStringOperators, + }} + playlists={playlistData} + uniqueId={filters.uniqueId} /> ), description: t('setting.language', { @@ -173,7 +175,6 @@ export const ApplicationSettings = () => { control: ( { if (!e) return; setSettings({ @@ -207,6 +207,8 @@ export const ApplicationSettings = () => { }, }); }} + searchable + value={fontSettings.builtIn} /> ), description: t('setting.font', { context: 'description', postProcess: 'sentenceCase' }), @@ -216,10 +218,7 @@ export const ApplicationSettings = () => { { control: ( { setSettings({ lyrics: { ...settings, translationTargetLanguage: value } }); }} + value={settings.translationTargetLanguage} /> ), description: t('setting.translationTargetLanguage', { @@ -145,10 +146,10 @@ export const LyricSettings = () => { control: ( { if (!e) return; @@ -49,7 +50,7 @@ export const WindowSettings = () => { postProcess: 'sentenceCase', }), onClose: () => { - window.electron.ipc!.send('app-restart'); + window.api.ipc!.send('app-restart'); }, title: t('common.restartRequired', { postProcess: 'sentenceCase', @@ -72,6 +73,7 @@ export const WindowSettings = () => { }, }); }} + value={settings.windowBarStyle} /> ), description: t('setting.windowBarStyle', { diff --git a/src/renderer/features/settings/components/window/window-tab.tsx b/src/renderer/features/settings/components/window/window-tab.tsx index 14b5c6a4..3e280385 100644 --- a/src/renderer/features/settings/components/window/window-tab.tsx +++ b/src/renderer/features/settings/components/window/window-tab.tsx @@ -1,11 +1,12 @@ import { Stack } from '@mantine/core'; +import isElectron from 'is-electron'; + +import { DiscordSettings } from '/@/renderer/features/settings/components/window/discord-settings'; +import { PasswordSettings } from '/@/renderer/features/settings/components/window/password-settings'; import { UpdateSettings } from '/@/renderer/features/settings/components/window/update-settings'; import { WindowSettings } from '/@/renderer/features/settings/components/window/window-settings'; -import { DiscordSettings } from '/@/renderer/features/settings/components/window/discord-settings'; -import isElectron from 'is-electron'; -import { PasswordSettings } from '/@/renderer/features/settings/components/window/password-settings'; -const utils = isElectron() ? window.electron.utils : null; +const utils = isElectron() ? window.api.utils : null; export const WindowTab = () => { return ( diff --git a/src/renderer/features/settings/routes/settings-route.tsx b/src/renderer/features/settings/routes/settings-route.tsx index 54f402ce..a3c41a61 100644 --- a/src/renderer/features/settings/routes/settings-route.tsx +++ b/src/renderer/features/settings/routes/settings-route.tsx @@ -1,9 +1,10 @@ import { Flex } from '@mantine/core'; +import { useState } from 'react'; + import { SettingsContent } from '/@/renderer/features/settings/components/settings-content'; import { SettingsHeader } from '/@/renderer/features/settings/components/settings-header'; -import { AnimatedPage } from '/@/renderer/features/shared'; import { SettingSearchContext } from '/@/renderer/features/settings/context/search-context'; -import { useState } from 'react'; +import { AnimatedPage } from '/@/renderer/features/shared'; const SettingsRoute = () => { const [search, setSearch] = useState(''); diff --git a/src/renderer/features/shared/components/animated-page.tsx b/src/renderer/features/shared/components/animated-page.tsx index aa0e5dc6..f5ab231a 100644 --- a/src/renderer/features/shared/components/animated-page.tsx +++ b/src/renderer/features/shared/components/animated-page.tsx @@ -1,6 +1,8 @@ import type { ReactNode, Ref } from 'react'; -import { forwardRef } from 'react'; + import { motion } from 'framer-motion'; +import { forwardRef } from 'react'; + import styles from './animated-page.module.scss'; interface AnimatedPageProps { @@ -17,9 +19,9 @@ export const AnimatedPage = forwardRef( ({ children }: AnimatedPageProps, ref: Ref) => { return ( ; - case LibraryItem.ARTIST: - return ; case LibraryItem.ALBUM_ARTIST: return ; + case LibraryItem.ARTIST: + return ; case LibraryItem.PLAYLIST: return ; default: diff --git a/src/renderer/features/shared/components/json-preview.tsx b/src/renderer/features/shared/components/json-preview.tsx index 51fbf13d..32a35ff8 100644 --- a/src/renderer/features/shared/components/json-preview.tsx +++ b/src/renderer/features/shared/components/json-preview.tsx @@ -1,5 +1,5 @@ interface JsonPreviewProps { - value: string | Record; + value: Record | string; } export const JsonPreview = ({ value }: JsonPreviewProps) => { diff --git a/src/renderer/features/shared/components/library-header-bar.tsx b/src/renderer/features/shared/components/library-header-bar.tsx index 3acfce5c..b746b8b9 100644 --- a/src/renderer/features/shared/components/library-header-bar.tsx +++ b/src/renderer/features/shared/components/library-header-bar.tsx @@ -1,8 +1,9 @@ -import { ReactNode } from 'react'; import { Box } from '@mantine/core'; +import { ReactNode } from 'react'; +import styled from 'styled-components'; + import { Paper, PaperProps, SpinnerIcon, TextTitle } from '/@/renderer/components'; import { PlayButton as PlayBtn } from '/@/renderer/features/shared/components/play-button'; -import styled from 'styled-components'; interface LibraryHeaderBarProps { children: ReactNode; @@ -47,8 +48,8 @@ const PlayButton = ({ onClick }: PlayButtonProps) => { ); diff --git a/src/renderer/features/shared/components/library-header.module.scss b/src/renderer/features/shared/components/library-header.module.css similarity index 100% rename from src/renderer/features/shared/components/library-header.module.scss rename to src/renderer/features/shared/components/library-header.module.css diff --git a/src/renderer/features/shared/components/library-header.tsx b/src/renderer/features/shared/components/library-header.tsx index 9bb9b833..f321f29d 100644 --- a/src/renderer/features/shared/components/library-header.tsx +++ b/src/renderer/features/shared/components/library-header.tsx @@ -1,11 +1,13 @@ -import { forwardRef, ReactNode, Ref, useCallback, useState } from 'react'; import { Center, Group } from '@mantine/core'; import { closeAllModals, openModal } from '@mantine/modals'; import { AutoTextSize } from 'auto-text-size'; import clsx from 'clsx'; +import { forwardRef, ReactNode, Ref, useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; -import styles from './library-header.module.scss'; + +import styles from './library-header.module.css'; + import { LibraryItem } from '/@/renderer/api/types'; import { Text } from '/@/renderer/components'; import { ItemImagePlaceholder } from '/@/renderer/features/shared/components/item-image-placeholder'; @@ -15,8 +17,8 @@ interface LibraryHeaderProps { background: string; blur?: number; children?: ReactNode; - imagePlaceholderUrl?: string | null; - imageUrl?: string | null; + imagePlaceholderUrl?: null | string; + imageUrl?: null | string; item: { route: string; type: LibraryItem }; title: string; } @@ -24,13 +26,13 @@ interface LibraryHeaderProps { export const LibraryHeader = forwardRef( ( { - imageUrl, - imagePlaceholderUrl, background, blur, - title, - item, children, + imagePlaceholderUrl, + imageUrl, + item, + title, }: LibraryHeaderProps, ref: Ref, ) => { @@ -46,10 +48,10 @@ export const LibraryHeader = forwardRef( switch (item.type) { case LibraryItem.ALBUM: return t('entity.album', { count: 1 }); - case LibraryItem.ARTIST: - return t('entity.artist', { count: 1 }); case LibraryItem.ALBUM_ARTIST: return t('entity.albumArtist', { count: 1 }); + case LibraryItem.ARTIST: + return t('entity.artist', { count: 1 }); case LibraryItem.PLAYLIST: return t('entity.playlist', { count: 1 }); case LibraryItem.SONG: @@ -66,12 +68,12 @@ export const LibraryHeader = forwardRef( openModal({ children: (
closeAllModals()} style={{ cursor: 'pointer', height: 'calc(100vh - 80px)', width: '100%', }} - onClick={() => closeAllModals()} > cover
openImage()} + onKeyDown={(event) => + [' ', 'Enter', 'Spacebar'].includes(event.key) && openImage() + } role="button" style={{ cursor: 'pointer' }} tabIndex={0} - onClick={() => openImage()} - onKeyDown={(event) => - ['Spacebar', ' ', 'Enter'].includes(event.key) && openImage() - } > {imageUrl && !isImageError ? ( cover ) : ( diff --git a/src/renderer/features/shared/components/order-toggle-button.tsx b/src/renderer/features/shared/components/order-toggle-button.tsx index d223374b..16435d55 100644 --- a/src/renderer/features/shared/components/order-toggle-button.tsx +++ b/src/renderer/features/shared/components/order-toggle-button.tsx @@ -1,6 +1,7 @@ import { ButtonProps } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import { RiSortAsc, RiSortDesc } from 'react-icons/ri'; + import { SortOrder } from '/@/renderer/api/types'; import { Button, Tooltip } from '/@/renderer/components'; @@ -10,7 +11,7 @@ interface OrderToggleButtonProps { sortOrder: SortOrder; } -export const OrderToggleButton = ({ sortOrder, onToggle, buttonProps }: OrderToggleButtonProps) => { +export const OrderToggleButton = ({ buttonProps, onToggle, sortOrder }: OrderToggleButtonProps) => { const { t } = useTranslation(); return ( <> diff --git a/src/renderer/features/shared/components/resize-handle.tsx b/src/renderer/features/shared/components/resize-handle.tsx index 81e6d11e..9446af64 100644 --- a/src/renderer/features/shared/components/resize-handle.tsx +++ b/src/renderer/features/shared/components/resize-handle.tsx @@ -2,7 +2,7 @@ import styled from 'styled-components'; export const ResizeHandle = styled.div<{ $isResizing: boolean; - $placement: 'top' | 'left' | 'bottom' | 'right'; + $placement: 'bottom' | 'left' | 'right' | 'top'; }>` position: absolute; top: ${(props) => props.$placement === 'top' && 0}; diff --git a/src/renderer/features/shared/hooks/use-handle-favorite.ts b/src/renderer/features/shared/hooks/use-handle-favorite.ts index ecdc1a36..b8ab1f40 100644 --- a/src/renderer/features/shared/hooks/use-handle-favorite.ts +++ b/src/renderer/features/shared/hooks/use-handle-favorite.ts @@ -1,4 +1,5 @@ import { MutableRefObject, useCallback } from 'react'; + import { LibraryItem } from '/@/renderer/api/types'; import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid'; import { useCreateFavorite } from '/@/renderer/features/shared/mutations/create-favorite-mutation'; @@ -6,8 +7,8 @@ import { useDeleteFavorite } from '/@/renderer/features/shared/mutations/delete- import { ServerListItem } from '/@/renderer/types'; interface HandleFavoriteProps { - gridRef: MutableRefObject; - server: ServerListItem | null; + gridRef: MutableRefObject; + server: null | ServerListItem; } export const useHandleFavorite = ({ gridRef, server }: HandleFavoriteProps) => { @@ -16,7 +17,7 @@ export const useHandleFavorite = ({ gridRef, server }: HandleFavoriteProps) => { const handleFavorite = useCallback( async (options: { id: string[]; isFavorite: boolean; itemType: LibraryItem }) => { - const { id, itemType, isFavorite } = options; + const { id, isFavorite, itemType } = options; try { if (isFavorite) { await deleteFavoriteMutation.mutateAsync({ diff --git a/src/renderer/features/shared/mutations/create-favorite-mutation.ts b/src/renderer/features/shared/mutations/create-favorite-mutation.ts index 8a811ff1..035ea324 100644 --- a/src/renderer/features/shared/mutations/create-favorite-mutation.ts +++ b/src/renderer/features/shared/mutations/create-favorite-mutation.ts @@ -1,5 +1,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import { AxiosError } from 'axios'; +import isElectron from 'is-electron'; + import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { @@ -11,10 +13,9 @@ import { } from '/@/renderer/api/types'; import { MutationHookArgs } from '/@/renderer/lib/react-query'; import { getServerById, useSetAlbumListItemDataById, useSetQueueFavorite } from '/@/renderer/store'; -import isElectron from 'is-electron'; import { useFavoriteEvent } from '/@/renderer/store/event.store'; -const remote = isElectron() ? window.electron.remote : null; +const remote = isElectron() ? window.api.remote : null; export const useCreateFavorite = (args: MutationHookArgs) => { const { options } = args || {}; @@ -26,7 +27,7 @@ export const useCreateFavorite = (args: MutationHookArgs) => { return useMutation< FavoriteResponse, AxiosError, - Omit, + Omit, null >({ mutationFn: (args) => { diff --git a/src/renderer/features/shared/mutations/delete-favorite-mutation.ts b/src/renderer/features/shared/mutations/delete-favorite-mutation.ts index a0275704..59b16a9a 100644 --- a/src/renderer/features/shared/mutations/delete-favorite-mutation.ts +++ b/src/renderer/features/shared/mutations/delete-favorite-mutation.ts @@ -1,5 +1,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import { AxiosError } from 'axios'; +import isElectron from 'is-electron'; + import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { @@ -11,10 +13,9 @@ import { } from '/@/renderer/api/types'; import { MutationHookArgs } from '/@/renderer/lib/react-query'; import { getServerById, useSetAlbumListItemDataById, useSetQueueFavorite } from '/@/renderer/store'; -import isElectron from 'is-electron'; import { useFavoriteEvent } from '/@/renderer/store/event.store'; -const remote = isElectron() ? window.electron.remote : null; +const remote = isElectron() ? window.api.remote : null; export const useDeleteFavorite = (args: MutationHookArgs) => { const { options } = args || {}; @@ -26,7 +27,7 @@ export const useDeleteFavorite = (args: MutationHookArgs) => { return useMutation< FavoriteResponse, AxiosError, - Omit, + Omit, null >({ mutationFn: (args) => { diff --git a/src/renderer/features/shared/mutations/set-rating-mutation.ts b/src/renderer/features/shared/mutations/set-rating-mutation.ts index eb3f1e5c..841fbc8b 100644 --- a/src/renderer/features/shared/mutations/set-rating-mutation.ts +++ b/src/renderer/features/shared/mutations/set-rating-mutation.ts @@ -1,23 +1,24 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import { AxiosError } from 'axios'; +import isElectron from 'is-electron'; + import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { Album, AlbumArtist, + AlbumArtistDetailResponse, + AlbumDetailResponse, AnyLibraryItems, LibraryItem, - SetRatingArgs, RatingResponse, - AlbumDetailResponse, - AlbumArtistDetailResponse, + SetRatingArgs, } from '/@/renderer/api/types'; import { MutationHookArgs } from '/@/renderer/lib/react-query'; import { getServerById, useSetAlbumListItemDataById, useSetQueueRating } from '/@/renderer/store'; -import isElectron from 'is-electron'; import { useRatingEvent } from '/@/renderer/store/event.store'; -const remote = isElectron() ? window.electron.remote : null; +const remote = isElectron() ? window.api.remote : null; export const useSetRating = (args: MutationHookArgs) => { const { options } = args || {}; @@ -29,8 +30,8 @@ export const useSetRating = (args: MutationHookArgs) => { return useMutation< RatingResponse, AxiosError, - Omit, - { previous: { items: AnyLibraryItems } | undefined } + Omit, + { previous: undefined | { items: AnyLibraryItems } } >({ mutationFn: (args) => { const server = getServerById(args.serverId); diff --git a/src/renderer/features/shared/queries/music-folders-query.ts b/src/renderer/features/shared/queries/music-folders-query.ts index 97042a42..40363f12 100644 --- a/src/renderer/features/shared/queries/music-folders-query.ts +++ b/src/renderer/features/shared/queries/music-folders-query.ts @@ -1,9 +1,11 @@ import { useQuery } from '@tanstack/react-query'; + +import { MusicFolderListQuery } from '../../../api/types'; +import { QueryHookArgs } from '../../../lib/react-query'; + import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { getServerById } from '/@/renderer/store'; -import { MusicFolderListQuery } from '../../../api/types'; -import { QueryHookArgs } from '../../../lib/react-query'; export const useMusicFolders = (args: QueryHookArgs) => { const { options, serverId } = args || {}; diff --git a/src/renderer/features/sharing/components/share-item-context-modal.tsx b/src/renderer/features/sharing/components/share-item-context-modal.tsx index ca915093..61d45f48 100644 --- a/src/renderer/features/sharing/components/share-item-context-modal.tsx +++ b/src/renderer/features/sharing/components/share-item-context-modal.tsx @@ -2,10 +2,12 @@ import { Box, Group, Stack, TextInput } from '@mantine/core'; import { DateTimePicker } from '@mantine/dates'; import { useForm } from '@mantine/form'; import { closeModal, ContextModalProps } from '@mantine/modals'; +import { useTranslation } from 'react-i18next'; + +import { useShareItem } from '../mutations/share-item-mutation'; + import { Button, Switch, toast } from '/@/renderer/components'; import { useCurrentServer } from '/@/renderer/store'; -import { useTranslation } from 'react-i18next'; -import { useShareItem } from '../mutations/share-item-mutation'; export const ShareItemContextModal = ({ id, @@ -122,9 +124,9 @@ export const ShareItemContextModal = ({ diff --git a/src/renderer/features/sharing/mutations/share-item-mutation.ts b/src/renderer/features/sharing/mutations/share-item-mutation.ts index ae774df0..30aae5ba 100644 --- a/src/renderer/features/sharing/mutations/share-item-mutation.ts +++ b/src/renderer/features/sharing/mutations/share-item-mutation.ts @@ -1,7 +1,8 @@ import { useMutation } from '@tanstack/react-query'; -import { AnyLibraryItems, ShareItemResponse, ShareItemArgs } from '/@/renderer/api/types'; import { AxiosError } from 'axios'; + import { api } from '/@/renderer/api'; +import { AnyLibraryItems, ShareItemArgs, ShareItemResponse } from '/@/renderer/api/types'; import { MutationHookArgs } from '/@/renderer/lib/react-query'; import { getServerById } from '/@/renderer/store'; @@ -11,8 +12,8 @@ export const useShareItem = (args: MutationHookArgs) => { return useMutation< ShareItemResponse, AxiosError, - Omit, - { previous: { items: AnyLibraryItems } | undefined } + Omit, + { previous: undefined | { items: AnyLibraryItems } } >({ mutationFn: (args) => { const server = getServerById(args.serverId); diff --git a/src/renderer/features/sidebar/components/action-bar.tsx b/src/renderer/features/sidebar/components/action-bar.tsx index b92d3dca..35376a42 100644 --- a/src/renderer/features/sidebar/components/action-bar.tsx +++ b/src/renderer/features/sidebar/components/action-bar.tsx @@ -1,8 +1,9 @@ import { Grid, Group } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { RiSearchLine, RiMenuFill, RiArrowLeftSLine, RiArrowRightSLine } from 'react-icons/ri'; +import { RiArrowLeftSLine, RiArrowRightSLine, RiMenuFill, RiSearchLine } from 'react-icons/ri'; import { useNavigate } from 'react-router'; import styled from 'styled-components'; + import { Button, DropdownMenu, TextInput } from '/@/renderer/components'; import { AppMenu } from '/@/renderer/features/titlebar/components/app-menu'; import { useContainerQuery } from '/@/renderer/hooks'; @@ -36,16 +37,16 @@ export const ActionBar = () => { > } - placeholder={t('common.search', { postProcess: 'titleCase' })} - size="md" onClick={open} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { open(); } }} + placeholder={t('common.search', { postProcess: 'titleCase' })} + readOnly + size="md" /> @@ -69,18 +70,18 @@ export const ActionBar = () => { @@ -95,10 +96,10 @@ export const ActionBar = () => { w="100%" > @@ -117,18 +118,18 @@ export const ActionBar = () => { diff --git a/src/renderer/features/sidebar/components/collapsed-sidebar-button.tsx b/src/renderer/features/sidebar/components/collapsed-sidebar-button.tsx index 73f35ef8..c927e827 100644 --- a/src/renderer/features/sidebar/components/collapsed-sidebar-button.tsx +++ b/src/renderer/features/sidebar/components/collapsed-sidebar-button.tsx @@ -1,5 +1,5 @@ -import { forwardRef, ReactNode } from 'react'; import { createPolymorphicComponent, Flex } from '@mantine/core'; +import { forwardRef, ReactNode } from 'react'; import styled from 'styled-components'; const Container = styled(Flex)<{ $active?: boolean; $disabled?: boolean }>` @@ -48,9 +48,9 @@ const _CollapsedSidebarButton = forwardRef { return ( {children} diff --git a/src/renderer/features/sidebar/components/collapsed-sidebar-item.tsx b/src/renderer/features/sidebar/components/collapsed-sidebar-item.tsx index e30122d3..3562e43a 100644 --- a/src/renderer/features/sidebar/components/collapsed-sidebar-item.tsx +++ b/src/renderer/features/sidebar/components/collapsed-sidebar-item.tsx @@ -3,6 +3,7 @@ import { motion } from 'framer-motion'; import { forwardRef, ReactNode } from 'react'; import { useMatch } from 'react-router'; import styled from 'styled-components'; + import { Text } from '/@/renderer/components'; const Container = styled(Flex)<{ $active?: boolean; $disabled?: boolean }>` @@ -71,17 +72,17 @@ interface CollapsedSidebarItemProps { } const _CollapsedSidebarItem = forwardRef( - ({ route, activeIcon, icon, label, disabled, ...props }: CollapsedSidebarItemProps, ref) => { + ({ activeIcon, disabled, icon, label, route, ...props }: CollapsedSidebarItemProps, ref) => { const match = useMatch(route || '/null'); const isMatch = Boolean(match); return ( {isMatch ? : null} diff --git a/src/renderer/features/sidebar/components/collapsed-sidebar.tsx b/src/renderer/features/sidebar/components/collapsed-sidebar.tsx index 4abadf10..606ba65e 100644 --- a/src/renderer/features/sidebar/components/collapsed-sidebar.tsx +++ b/src/renderer/features/sidebar/components/collapsed-sidebar.tsx @@ -1,10 +1,11 @@ -import { useMemo } from 'react'; import { Group, UnstyledButton } from '@mantine/core'; import { motion } from 'framer-motion'; +import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { RiArrowLeftSLine, RiArrowRightSLine, RiMenuFill } from 'react-icons/ri'; import { NavLink, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; + import { DropdownMenu, ScrollArea } from '/@/renderer/components'; import { CollapsedSidebarButton } from '/@/renderer/features/sidebar/components/collapsed-sidebar-button'; import { CollapsedSidebarItem } from '/@/renderer/features/sidebar/components/collapsed-sidebar-item'; @@ -28,7 +29,7 @@ export const CollapsedSidebar = () => { const { t } = useTranslation(); const navigate = useNavigate(); const { windowBarStyle } = useWindowSettings(); - const { sidebarItems, sidebarCollapsedNavigation } = useGeneralSettings(); + const { sidebarCollapsedNavigation, sidebarItems } = useGeneralSettings(); const translatedSidebarItemMap = useMemo( () => ({ @@ -68,8 +69,8 @@ export const CollapsedSidebar = () => { return ( {sidebarCollapsedNavigation && ( { {sidebarItemsWithRoute.map((item) => ( { size="25" /> } + key={item.id} label={item.label} route={item.route} to={item.route} diff --git a/src/renderer/features/sidebar/components/sidebar-icon.tsx b/src/renderer/features/sidebar/components/sidebar-icon.tsx index ef87e702..6ed341ac 100644 --- a/src/renderer/features/sidebar/components/sidebar-icon.tsx +++ b/src/renderer/features/sidebar/components/sidebar-icon.tsx @@ -20,9 +20,10 @@ import { RiUserVoiceFill, RiUserVoiceLine, } from 'react-icons/ri'; -import { AppRoute } from '/@/renderer/router/routes'; import { generatePath } from 'react-router'; + import { LibraryItem } from '/@/renderer/api/types'; +import { AppRoute } from '/@/renderer/router/routes'; interface SidebarIconProps { active?: boolean; @@ -35,36 +36,36 @@ export const SidebarIcon = ({ active, route, size }: SidebarIconProps) => { case AppRoute.HOME: if (active) return ; return ; - case AppRoute.LIBRARY_ALBUMS: - if (active) return ; - return ; case AppRoute.LIBRARY_ALBUM_ARTISTS: if (active) return ; return ; + case AppRoute.LIBRARY_ALBUMS: + if (active) return ; + return ; case AppRoute.LIBRARY_ARTISTS: if (active) return ; return ; - case AppRoute.PLAYLISTS: - if (active) return ; - return ; - case AppRoute.LIBRARY_SONGS: - if (active) return ; - return ; case AppRoute.LIBRARY_FOLDERS: if (active) return ; return ; case AppRoute.LIBRARY_GENRES: if (active) return ; return ; - case generatePath(AppRoute.SEARCH, { itemType: LibraryItem.SONG }): - if (active) return ; - return ; - case AppRoute.SETTINGS: - if (active) return ; - return ; + case AppRoute.LIBRARY_SONGS: + if (active) return ; + return ; case AppRoute.NOW_PLAYING: if (active) return ; return ; + case AppRoute.PLAYLISTS: + if (active) return ; + return ; + case AppRoute.SETTINGS: + if (active) return ; + return ; + case generatePath(AppRoute.SEARCH, { itemType: LibraryItem.SONG }): + if (active) return ; + return ; default: return ; } diff --git a/src/renderer/features/sidebar/components/sidebar-item.tsx b/src/renderer/features/sidebar/components/sidebar-item.tsx index f23ffdc5..5a8f00b4 100644 --- a/src/renderer/features/sidebar/components/sidebar-item.tsx +++ b/src/renderer/features/sidebar/components/sidebar-item.tsx @@ -1,6 +1,7 @@ import type { ReactNode } from 'react'; -import { createPolymorphicComponent, Flex, FlexProps } from '@mantine/core'; import type { LinkProps } from 'react-router-dom'; + +import { createPolymorphicComponent, Flex, FlexProps } from '@mantine/core'; import { Link } from 'react-router-dom'; import styled, { css } from 'styled-components'; @@ -46,7 +47,7 @@ const _ItemLink = styled(StyledItem)` const ItemLink = createPolymorphicComponent<'a', ListItemProps>(_ItemLink); -export const SidebarItem = ({ to, children, ...props }: ListItemProps) => { +export const SidebarItem = ({ children, to, ...props }: ListItemProps) => { if (to) { return ( { +const PlaylistRow = ({ data, index, style }: ListChildComponentProps) => { const { t } = useTranslation(); if (Array.isArray(data?.items[index])) { @@ -40,6 +41,7 @@ const PlaylistRow = ({ index, data, style }: ListChildComponentProps) => { {t('page.sidebar.shared', { postProcess: 'titleCase' })} @@ -174,7 +175,7 @@ const PlaylistRow = ({ index, data, style }: ListChildComponentProps) => { }; export const SidebarPlaylistList = () => { - const { isScrollbarHidden, hideScrollbarElementProps } = useHideScrollbar(0); + const { hideScrollbarElementProps, isScrollbarHidden } = useHideScrollbar(0); const handlePlayQueueAdd = usePlayQueueAdd(); const { sidebarCollapseShared } = useGeneralSettings(); const { toggleSidebarCollapseShare } = useSettingsStoreActions(); @@ -218,7 +219,7 @@ export const SidebarPlaylistList = () => { return { ...base, items: data?.items }; } - const owned: Array void]> = []; + const owned: Array<[boolean, () => void] | Playlist> = []; const shared: Playlist[] = []; for (const playlist of data.items) { diff --git a/src/renderer/features/sidebar/components/sidebar.tsx b/src/renderer/features/sidebar/components/sidebar.tsx index 3ba5602b..8cd901aa 100644 --- a/src/renderer/features/sidebar/components/sidebar.tsx +++ b/src/renderer/features/sidebar/components/sidebar.tsx @@ -1,16 +1,18 @@ -import { MouseEvent, useMemo } from 'react'; import { Box, Center, Divider, Group, Stack } from '@mantine/core'; import { closeAllModals, openModal } from '@mantine/modals'; import { AnimatePresence, motion } from 'framer-motion'; +import { MouseEvent, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { RiAddFill, RiArrowDownSLine, RiDiscLine, RiListUnordered } from 'react-icons/ri'; import { Link, useLocation } from 'react-router-dom'; import styled from 'styled-components'; + import { SidebarItemType, useGeneralSettings, useWindowSettings, } from '../../../store/settings.store'; + import { ServerType } from '/@/renderer/api/types'; import { Button, MotionStack, Tooltip } from '/@/renderer/components'; import { CreatePlaylistForm } from '/@/renderer/features/playlists'; @@ -137,8 +139,8 @@ export const Sidebar = () => { return ( { @@ -233,14 +235,14 @@ export const Sidebar = () => { > {showImage && ( { @@ -637,22 +640,22 @@ export const SongListHeaderFilters = ({ {t('table.config.view.card', { postProcess: 'sentenceCase' })} {t('table.config.view.poster', { postProcess: 'sentenceCase' })} {t('table.config.view.table', { postProcess: 'sentenceCase' })} @@ -707,8 +710,8 @@ export const SongListHeaderFilters = ({ clearable data={SONG_TABLE_COLUMNS} defaultValue={table?.columns.map((column) => column.column)} - width={300} onChange={handleTableColumns} + width={300} /> diff --git a/src/renderer/features/songs/components/song-list-header.tsx b/src/renderer/features/songs/components/song-list-header.tsx index 055d3ce8..ac48198a 100644 --- a/src/renderer/features/songs/components/song-list-header.tsx +++ b/src/renderer/features/songs/components/song-list-header.tsx @@ -1,21 +1,23 @@ -import { ChangeEvent, MutableRefObject, useEffect, useRef } from 'react'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + import { Flex, Group, Stack } from '@mantine/core'; import debounce from 'lodash/debounce'; +import { ChangeEvent, MutableRefObject, useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; + import { LibraryItem, SongListQuery } from '/@/renderer/api/types'; import { PageHeader, SearchInput } from '/@/renderer/components'; +import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid'; import { FilterBar, LibraryHeaderBar } from '/@/renderer/features/shared'; import { SongListHeaderFilters } from '/@/renderer/features/songs/components/song-list-header-filters'; import { useContainerQuery } from '/@/renderer/hooks'; +import { useDisplayRefresh } from '/@/renderer/hooks/use-display-refresh'; import { SongListFilter, useCurrentServer } from '/@/renderer/store'; import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; -import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid'; -import { useDisplayRefresh } from '/@/renderer/hooks/use-display-refresh'; interface SongListHeaderProps { genreId?: string; - gridRef: MutableRefObject; + gridRef: MutableRefObject; itemCount?: number; tableRef: MutableRefObject; title?: string; @@ -24,9 +26,9 @@ interface SongListHeaderProps { export const SongListHeader = ({ genreId, gridRef, - title, itemCount, tableRef, + title, }: SongListHeaderProps) => { const { t } = useTranslation(); const server = useCurrentServer(); @@ -90,8 +92,8 @@ export const SongListHeader = ({ diff --git a/src/renderer/features/songs/components/song-list-table-view.tsx b/src/renderer/features/songs/components/song-list-table-view.tsx index ff498dd3..4574529c 100644 --- a/src/renderer/features/songs/components/song-list-table-view.tsx +++ b/src/renderer/features/songs/components/song-list-table-view.tsx @@ -1,6 +1,8 @@ -import { RowDoubleClickedEvent } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; + +import { RowDoubleClickedEvent } from '@ag-grid-community/core'; import { MutableRefObject } from 'react'; + import { LibraryItem, QueueSong, SongListQuery } from '/@/renderer/api/types'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; import { VirtualTable } from '/@/renderer/components/virtual-table'; @@ -21,9 +23,9 @@ interface SongListTableViewProps { tableRef: MutableRefObject; } -export const SongListTableView = ({ tableRef, itemCount }: SongListTableViewProps) => { +export const SongListTableView = ({ itemCount, tableRef }: SongListTableViewProps) => { const server = useCurrentServer(); - const { pageKey, id, handlePlay, customFilters } = useListContext(); + const { customFilters, handlePlay, id, pageKey } = useListContext(); const isFocused = useAppFocus(); const currentSong = useCurrentSong(); const status = useCurrentStatus(); @@ -56,15 +58,15 @@ export const SongListTableView = ({ tableRef, itemCount }: SongListTableViewProp key={`table-${tableProps.rowHeight}-${server?.id}`} ref={tableRef} {...tableProps} - shouldUpdateSong context={{ ...tableProps.context, currentSong, isFocused, status, }} - rowClassRules={rowClassRules} onRowDoubleClicked={handleRowDoubleClick} + rowClassRules={rowClassRules} + shouldUpdateSong /> ); diff --git a/src/renderer/features/songs/components/subsonic-song-filter.tsx b/src/renderer/features/songs/components/subsonic-song-filter.tsx index fae5546b..a29f67d8 100644 --- a/src/renderer/features/songs/components/subsonic-song-filter.tsx +++ b/src/renderer/features/songs/components/subsonic-song-filter.tsx @@ -1,11 +1,12 @@ -import { ChangeEvent, useMemo } from 'react'; import { Divider, Group, Stack } from '@mantine/core'; import debounce from 'lodash/debounce'; +import { ChangeEvent, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; + import { GenreListSort, LibraryItem, SongListQuery, SortOrder } from '/@/renderer/api/types'; import { Select, Switch, Text } from '/@/renderer/components'; import { useGenreList } from '/@/renderer/features/genres'; import { SongListFilter, useListFilterByKey, useListStoreActions } from '/@/renderer/store'; -import { useTranslation } from 'react-i18next'; interface SubsonicSongFiltersProps { customFilters?: Partial; @@ -43,7 +44,7 @@ export const SubsonicSongFilters = ({ })); }, [genreListQuery.data]); - const handleGenresFilter = debounce((e: string | null) => { + const handleGenresFilter = debounce((e: null | string) => { const updatedFilters = setFilter({ customFilters, data: { @@ -87,8 +88,8 @@ export const SubsonicSongFilters = ({ ))} @@ -97,13 +98,13 @@ export const SubsonicSongFilters = ({ {!isGenrePage && (