73 lines
2.7 KiB
TypeScript
73 lines
2.7 KiB
TypeScript
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<T extends string>(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,
|
|
};
|
|
}
|