Files
api/web/nuxt.config.ts
Eli Bosley 3b00fec5fd chore: Remove legacy store modules and add new API key and reporting services (#1536)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added developer CLI tools for toggling GraphQL sandbox and modal
testing utilities.
* Introduced a "Show Activation Modal" developer component for UI
testing.
  * Added system initial setup detection and related GraphQL queries.
* Enhanced login and welcome pages with dynamic server info and initial
setup state.
  * Improved SSO button with internationalization and error handling.
* Added internal CLI admin API key management service and internal
GraphQL client service.
* Introduced comprehensive API report generation service for system and
service status.
* Added CLI commands and GraphQL mutations/queries for plugin and SSO
user management.
* Added new modal target components and improved teleport target
detection.

* **Enhancements**
* Refined modal dialog targeting and teleportation for flexible UI
placement.
* Updated modal components and stores for improved activation/welcome
modal control.
  * Improved plugin and SSO user management via CLI through GraphQL API.
* Refactored partner logo components to use props instead of store
dependencies.
  * Enhanced styling and accessibility for buttons and modals.
* Streamlined Tailwind CSS integration with shared styles and updated
theme variables.
* Improved GraphQL module configuration to avoid directive conflicts in
tests.
  * Adjusted Vite config for better dependency handling in test mode.
  * Improved error handling and logging in CLI commands and services.
* Reordered imports and refined component class bindings for UI
consistency.

* **Bug Fixes**
* Resolved issues with duplicate script tags and component registration
in the web UI.
* Fixed modal close button visibility and activation modal state
handling.
* Added error handling and logging improvements across CLI commands and
services.
  * Fixed newline issues in last-download-time fixture files.

* **Chores**
* Added and updated numerous tests for CLI commands, services, and UI
components.
* Updated translation files and localization resources for new UI
messages.
* Adjusted environment, configuration, and dependency files for improved
development and test workflows.
  * Cleaned up unused imports and mocks in tests.
  * Reorganized exports and barrel files in shared and UI modules.
  * Added integration and dependency resolution tests for core modules.

* **Removals & Refactoring**
* Removed legacy Redux state management, configuration, and UPnP logic
from the backend.
* Eliminated deprecated GraphQL subscriptions and client code related to
registration and mothership.
* Removed direct store manipulation and replaced with service-based
approaches in CLI commands.
  * Deleted unused or redundant test files and configuration listeners.
* Refactored SSO user service to consolidate add/remove operations into
a single update method.
* Simplified API key services with new methods for automatic key
management.
* Replaced direct plugin and SSO user service calls with GraphQL client
interactions in CLI commands.
* Removed complex theme fallback and dark mode CSS rules, replacing with
streamlined static theme variables.
* Cleaned up Tailwind CSS configuration and removed deprecated local
styles.
* Removed multiple internal utility files and replaced with simplified
or centralized implementations.
* Removed deprecated local configuration and synchronization files and
listeners.
  * Removed UPnP helper functions and job management classes.
* Refactored server resolver to dynamically construct local server data
internally.
* Removed CORS handler and replaced with simplified or externalized
logic.
* Removed store synchronization and registration event pubsub handling.
* Removed GraphQL client creation utilities for internal API
communication.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-07-25 15:07:37 -04:00

237 lines
7.6 KiB
TypeScript

import path from 'path';
import tailwindcss from '@tailwindcss/vite';
import removeConsole from 'vite-plugin-remove-console';
import type { PluginOption, UserConfig } from 'vite';
/**
* Used to avoid redeclaring variables in the webgui codebase.
* @see alt solution https://github.com/terser/terser/issues/1001, https://github.com/terser/terser/pull/1038
*/
function terserReservations(inputStr: string) {
const combinations = ['ace'];
// Add 1-character combinations
for (let i = 0; i < inputStr.length; i++) {
combinations.push(inputStr[i]);
}
// Add 2-character combinations
for (let i = 0; i < inputStr.length; i++) {
for (let j = 0; j < inputStr.length; j++) {
combinations.push(inputStr[i] + inputStr[j]);
}
}
return combinations;
}
const charsToReserve = '_$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const dropConsole = process.env.VITE_ALLOW_CONSOLE_LOGS !== 'true';
console.log(dropConsole ? 'WARN: Console logs are disabled' : 'INFO: Console logs are enabled');
const assetsDir = path.join(__dirname, '../api/dev/webGui/');
/**
* Create a tag configuration
*/
const createWebComponentTag = (name: string, path: string, appContext: string) => ({
async: false,
name,
path,
appContext
});
/**
* Shared terser options for consistent minification
*/
const sharedTerserOptions = {
mangle: {
reserved: terserReservations(charsToReserve),
toplevel: true,
},
};
/**
* Shared plugins configuration
*/
const getSharedPlugins = (includeJQueryIsolation = false) => {
const plugins: PluginOption[] = [];
// Add Tailwind CSS plugin
plugins.push(tailwindcss());
// Remove console logs in production
if (dropConsole) {
plugins.push(
removeConsole({
includes: ['log', 'info', 'debug'],
})
);
}
// Add jQuery isolation plugin for custom elements
if (includeJQueryIsolation) {
plugins.push({
name: 'jquery-isolation',
// eslint-disable-next-line @typescript-eslint/no-explicit-any
generateBundle(options: any, bundle: any) {
// Find the main JS file
const jsFile = Object.keys(bundle).find((key) => key.endsWith('.js'));
if (jsFile && bundle[jsFile] && 'code' in bundle[jsFile]) {
const originalCode = bundle[jsFile].code;
// Wrap the entire bundle to preserve and restore jQuery
bundle[jsFile].code = `
(function() {
// Preserve the original jQuery $ if it exists
var originalJQuery = (typeof window !== 'undefined' && typeof window.$ !== 'undefined') ? window.$ : undefined;
// Temporarily clear $ to avoid conflicts
if (typeof window !== 'undefined' && typeof window.$ !== 'undefined') {
window.$ = undefined;
}
// Execute the web component code
${originalCode}
// Restore jQuery $ if it was originally defined
if (originalJQuery !== undefined && typeof window !== 'undefined') {
window.$ = originalJQuery;
}
})();
`;
}
},
});
}
return plugins.filter(Boolean);
};
/**
* Shared define configuration
*/
const sharedDefine = {
'globalThis.__DEV__': process.env.NODE_ENV === 'development',
__VUE_PROD_DEVTOOLS__: false,
};
/**
* Apply shared Vite configuration to a config object
*/
const applySharedViteConfig = (config: UserConfig, includeJQueryIsolation = false) => {
if (!config.plugins) config.plugins = [];
if (!config.define) config.define = {};
if (!config.build) config.build = {};
// Add shared plugins
config.plugins.push(...getSharedPlugins(includeJQueryIsolation));
// Merge define values
Object.assign(config.define, sharedDefine);
// Apply build configuration
config.build.minify = 'terser';
config.build.terserOptions = sharedTerserOptions;
return config;
};
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
nitro: {
publicAssets: [
{
baseURL: '/webGui/',
dir: assetsDir,
},
],
},
devServer: {
port: 4321,
},
css: ['@/assets/main.css'],
devtools: {
enabled: process.env.NODE_ENV === 'development',
},
modules: ['@vueuse/nuxt', '@pinia/nuxt', 'nuxt-custom-elements', '@nuxt/eslint', '@nuxt/ui'],
ui: {
theme: {
colors: ['primary'],
},
},
// Disable auto-imports
imports: {
autoImport: false,
},
// Properly handle ES modules in testing and build environments
build: {
transpile: [/node_modules\/.*\.mjs$/],
},
ignore: ['/webGui/images'],
// Disable component auto-imports
components: false,
vite: {
plugins: getSharedPlugins(),
define: sharedDefine,
build: {
minify: 'terser',
terserOptions: sharedTerserOptions,
},
},
customElements: {
analyzer: process.env.NODE_ENV !== 'test',
entries: [
// @ts-expect-error The nuxt-custom-elements module types don't perfectly match our configuration object structure.
// The custom elements configuration requires specific properties and methods that may not align with the
// module's TypeScript definitions, particularly around the viteExtend function and tag configuration format.
{
name: 'UnraidComponents',
viteExtend(config: UserConfig) {
const sharedConfig = applySharedViteConfig(config, true);
// Optimize CSS while keeping it inlined for functionality
if (!sharedConfig.css) sharedConfig.css = {};
sharedConfig.css.devSourcemap = process.env.NODE_ENV === 'development';
return sharedConfig;
},
tags: [
createWebComponentTag('UnraidAuth', '@/components/Auth.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidConnectSettings', '@/components/ConnectSettings/ConnectSettings.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidDownloadApiLogs', '@/components/DownloadApiLogs.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidHeaderOsVersion', '@/components/HeaderOsVersion.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidModals', '@/components/Modals.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidUserProfile', '@/components/UserProfile.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidUpdateOs', '@/components/UpdateOs.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidDowngradeOs', '@/components/DowngradeOs.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidRegistration', '@/components/Registration.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidWanIpCheck', '@/components/WanIpCheck.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidWelcomeModal', '@/components/Activation/WelcomeModal.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidSsoButton', '@/components/SsoButton.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidLogViewer', '@/components/Logs/LogViewer.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidThemeSwitcher', '@/components/ThemeSwitcher.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidApiKeyManager', '@/components/ApiKeyPage.ce', '@/components/Wrapper/web-component-plugins'),
createWebComponentTag('UnraidDevModalTest', '@/components/DevModalTest.ce', '@/components/Wrapper/web-component-plugins'),
],
},
],
},
compatibilityDate: '2024-12-05',
ssr: false,
});