import type { PluginWorkspaceFilters, PluginWorkspaceKey, PluginWorkspaceScope, PluginWorkspaceSource, PluginWorkspaceState, } from './plugin-workspace-model'; const SCOPES: readonly PluginWorkspaceScope[] = ['all', 'project']; const SOURCES: readonly PluginWorkspaceSource[] = ['all', 'official', 'local']; const STATES: readonly PluginWorkspaceState[] = [ 'all', 'available', 'mine', 'enabled', 'update', 'unavailable', ]; function member(value: string | null, values: readonly T[]): value is T { return value !== null && values.includes(value as T); } function pluginKey(value: string | null): PluginWorkspaceKey | null { if (!value) return null; if (value.startsWith('official:') && value.length > 'official:'.length) return value as `official:${string}`; if (value.startsWith('local:') && value.length > 'local:'.length) return value as `local:${string}`; if (value.startsWith('retained:') && value.length > 'retained:'.length) return value as `retained:${string}`; return null; } export function parsePluginWorkspaceSearch( search: URLSearchParams, hasActiveProject: boolean, ): PluginWorkspaceFilters { const defaultScope: PluginWorkspaceScope = hasActiveProject ? 'project' : 'all'; const requestedScope = search.get('scope'); const requestedSource = search.get('source'); const requestedState = search.get('state'); const parsedScope = member(requestedScope, SCOPES) ? requestedScope : defaultScope; return { scope: parsedScope === 'project' && !hasActiveProject ? 'all' : parsedScope, source: member(requestedSource, SOURCES) ? requestedSource : 'all', state: member(requestedState, STATES) ? requestedState : 'all', search: search.get('q')?.trim() ?? '', selectedKey: pluginKey(search.get('plugin')), }; } export function serializePluginWorkspaceSearch(filters: PluginWorkspaceFilters): URLSearchParams { const search = new URLSearchParams(); search.set('scope', filters.scope); search.set('source', filters.source); search.set('state', filters.state); const query = filters.search.trim(); if (query) search.set('q', query); if (filters.selectedKey) search.set('plugin', filters.selectedKey); return search; } export interface PluginWorkspaceSearchResolution { filters: PluginWorkspaceFilters; canonicalSearch: string; scopeFallback: boolean; } export function resolvePluginWorkspaceSearch( search: URLSearchParams, hasActiveProject: boolean, ): PluginWorkspaceSearchResolution { const filters = parsePluginWorkspaceSearch(search, hasActiveProject); return { filters, canonicalSearch: serializePluginWorkspaceSearch(filters).toString(), scopeFallback: search.get('scope') === 'project' && !hasActiveProject, }; }