From bc487629253f5a654330d38f9c0329781e0830e0 Mon Sep 17 00:00:00 2001 From: FragginWagon Date: Wed, 28 Jan 2026 22:53:33 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20feature=20flags=20configurati?= =?UTF-8?q?on=20for=20Pokedex=20Online?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/config/feature-flags.js | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 code/websites/pokedex.online/src/config/feature-flags.js diff --git a/code/websites/pokedex.online/src/config/feature-flags.js b/code/websites/pokedex.online/src/config/feature-flags.js new file mode 100644 index 0000000..f99fcc1 --- /dev/null +++ b/code/websites/pokedex.online/src/config/feature-flags.js @@ -0,0 +1,132 @@ +/** + * Feature Flags Configuration + * + * Defines all feature flags with metadata. + * Uses build-time obfuscation for production security. + * + * Pattern: + * - Development: Flags easily toggled via Developer Tools (Ctrl+Shift+D) + * - Production: Flags obfuscated and require permission-based backend query + * - All flags checked at runtime via useFeatureFlags composable + * + * Usage in components: + * ```javascript + * const { isEnabled } = useFeatureFlags(); + * if (isEnabled('experimental-search')) { ... } + * ``` + */ + +export const FEATURE_FLAGS = { + // Gamemaster Explorer Features + EXPERIMENTAL_SEARCH: { + name: 'experimental-search', + description: 'Enable experimental search with regex support', + enabled: false, + requiredPermission: null, + tags: ['gamemaster', 'search'] + }, + + GAMEMASTER_DIFF_VIEWER: { + name: 'gamemaster-diff-viewer', + description: 'Enable diff viewer for gamemaster file comparisons', + enabled: false, + requiredPermission: 'gamemaster-advanced', + tags: ['gamemaster', 'ui'] + }, + + GAMEMASTER_BOOKMARKS: { + name: 'gamemaster-bookmarks', + description: 'Enable bookmarking feature for favorite gamemasters', + enabled: false, + requiredPermission: null, + tags: ['gamemaster', 'storage'] + }, + + // Challonge Test Features + CHALLONGE_CACHED_TOURNAMENTS: { + name: 'challonge-cached-tournaments', + description: 'Cache tournament data for faster loading', + enabled: false, + requiredPermission: 'challonge-advanced', + tags: ['challonge', 'performance'] + }, + + CHALLONGE_EXPORT_CSV: { + name: 'challonge-export-csv', + description: 'Allow exporting tournament data to CSV', + enabled: false, + requiredPermission: null, + tags: ['challonge', 'export'] + }, + + // Developer/Admin Features + DEVELOPER_TOOLS: { + name: 'developer-tools', + description: 'Show developer tools panel (Ctrl+Shift+D)', + enabled: process.env.NODE_ENV === 'development', + requiredPermission: null, + tags: ['developer'] + }, + + ADMIN_PANEL: { + name: 'admin-panel', + description: 'Show admin panel with system information', + enabled: false, + requiredPermission: 'admin', + tags: ['admin', 'maintenance'] + }, + + // Performance Features + ENABLE_CACHING: { + name: 'enable-caching', + description: 'Enable client-side caching for API responses', + enabled: true, + requiredPermission: null, + tags: ['performance'] + }, + + // UI Features + DARK_MODE: { + name: 'dark-mode', + description: 'Enable dark mode theme', + enabled: false, + requiredPermission: null, + tags: ['ui', 'theme'] + } +}; + +/** + * Get all feature flags + * @returns {Object} All feature flags + */ +export function getAllFlags() { + return FEATURE_FLAGS; +} + +/** + * Get flag by name + * @param {string} name - Flag name + * @returns {Object|null} Flag object or null if not found + */ +export function getFlag(name) { + return Object.values(FEATURE_FLAGS).find(flag => flag.name === name) || null; +} + +/** + * Get all flags for a specific tag + * @param {string} tag - Tag name + * @returns {Object[]} Array of flags with the tag + */ +export function getFlagsByTag(tag) { + return Object.values(FEATURE_FLAGS).filter(flag => flag.tags.includes(tag)); +} + +/** + * Check if flag requires specific permission + * @param {string} name - Flag name + * @returns {string|null} Required permission or null if no permission required + */ +export function getFlagPermission(name) { + const flag = getFlag(name); + return flag ? flag.requiredPermission : null; +}