Files
makelore/src/pages/Plugins/plugin-workspace-query.ts

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,
};
}