Skip to main content
Glama
MIT License
27,120
19,787
  • Linux
  • Apple
urlParams.ts•6.67 kB
import type { PackOptions } from '../composables/usePackOptions'; // URL parameter constants const BOOLEAN_PARAMS = [ 'removeComments', 'removeEmptyLines', 'showLineNumbers', 'fileSummary', 'directoryStructure', 'outputParsable', 'compress', ] as const; const VALID_FORMATS = ['xml', 'markdown', 'plain'] as const; const URL_PARAM_KEYS = ['repo', 'format', 'style', 'include', 'ignore', ...BOOLEAN_PARAMS] as const; // Key mapping for internal names to URL parameter names const KEY_MAPPING: Record<string, string> = { includePatterns: 'include', ignorePatterns: 'ignore', }; // Helper function to get URL parameter key from internal key function getUrlParamKey(internalKey: string): string { return KEY_MAPPING[internalKey] || internalKey; } // Helper function to validate URL parameter values export function validateUrlParameters(params: Record<string, unknown>): { isValid: boolean; errors: string[] } { const errors: string[] = []; // Validate format parameter if (params.format && !(VALID_FORMATS as readonly string[]).includes(params.format as string)) { errors.push(`Invalid format: ${params.format}. Must be one of: ${VALID_FORMATS.join(', ')}`); } // Validate URL length to prevent browser limit issues const urlSearchParams = new URLSearchParams(); for (const [key, value] of Object.entries(params)) { if (value !== undefined && value !== null) { urlSearchParams.set(key, String(value)); } } const maxUrlLength = 2000; // Conservative limit for browser compatibility if (urlSearchParams.toString().length > maxUrlLength) { errors.push( `URL parameters too long (${urlSearchParams.toString().length} chars). Maximum allowed: ${maxUrlLength}`, ); } return { isValid: errors.length === 0, errors, }; } // Helper function to check if any options differ from defaults export function hasNonDefaultValues( inputUrl: string, packOptions: Record<string, unknown>, defaultOptions: Record<string, unknown>, ): boolean { // Check if there's input URL if (inputUrl && inputUrl.trim() !== '') { return true; } // Check if any pack option differs from default for (const [key, value] of Object.entries(packOptions)) { const defaultValue = defaultOptions[key]; if (typeof value === 'string' && typeof defaultValue === 'string') { if (value.trim() !== defaultValue.trim()) { return true; } } else if (value !== defaultValue) { return true; } } return false; } /** * Parses URL query parameters and returns pack options and repository URL. * Supports backward compatibility with 'style' parameter as alias for 'format'. * * @returns Parsed options object with repository URL and pack options */ export function parseUrlParameters(): Partial<PackOptions & { repo?: string }> { if (typeof window === 'undefined') { return {}; } const urlParams = new URLSearchParams(window.location.search); const params: Partial<PackOptions & { repo?: string }> = {}; // Repository URL parameter const repo = urlParams.get('repo'); if (repo) { params.repo = repo.trim(); } // Format and Style parameters (with conflict handling) const format = urlParams.get('format'); const style = urlParams.get('style'); if ( format && (VALID_FORMATS as readonly string[]).includes(format) && style && (VALID_FORMATS as readonly string[]).includes(style) ) { // Both present: prefer format, warn about conflict params.format = format as (typeof VALID_FORMATS)[number]; console.warn( `Both 'format' and 'style' URL parameters are present. Using 'format=${format}' and ignoring 'style=${style}'.`, ); } else if (format && (VALID_FORMATS as readonly string[]).includes(format)) { params.format = format as (typeof VALID_FORMATS)[number]; } else if (style && (VALID_FORMATS as readonly string[]).includes(style)) { params.format = style as (typeof VALID_FORMATS)[number]; } // Include patterns const include = urlParams.get('include'); if (include) { params.includePatterns = include; } // Ignore patterns const ignore = urlParams.get('ignore'); if (ignore) { params.ignorePatterns = ignore; } // Boolean parameters for (const param of BOOLEAN_PARAMS) { const value = urlParams.get(param); if (value !== null) { // Accept various truthy values: true, 1, yes, on params[param] = ['true', '1', 'yes', 'on'].includes(value.toLowerCase()); } } return params; } /** * Updates URL query parameters with the provided options. * Validates parameters and provides error handling for URL length limits. * * @param options - Pack options and repository URL to set in URL * @returns Result object with success status and optional error message */ export function updateUrlParameters(options: Partial<PackOptions & { repo?: string }>): { success: boolean; error?: string; } { if (typeof window === 'undefined') { return { success: false, error: 'Window object not available (SSR environment)' }; } try { // Validate parameters before updating URL const validation = validateUrlParameters(options); if (!validation.isValid) { // If validation fails due to URL length, return error instead of continuing const hasLengthError = validation.errors.some((error) => error.includes('too long')); if (hasLengthError) { return { success: false, error: validation.errors.join('; ') }; } // For other validation errors, just warn and continue console.warn('URL parameter validation failed:', validation.errors); } const url = new URL(window.location.href); const params = url.searchParams; // Clear existing repomix-related parameters for (const key of URL_PARAM_KEYS) { params.delete(key); } // Add new parameters for (const [key, value] of Object.entries(options)) { if (value !== undefined && value !== null) { const urlParamKey = getUrlParamKey(key); if (typeof value === 'boolean') { params.set(urlParamKey, value.toString()); } else if (typeof value === 'string' && value.trim() !== '') { params.set(urlParamKey, value.trim()); } } } // Update URL without reloading the page window.history.replaceState({}, '', url.toString()); return { success: true }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred while updating URL'; console.error('Failed to update URL parameters:', errorMessage); return { success: false, error: errorMessage }; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yamadashy/repomix'

If you have feedback or need assistance with the MCP directory API, please join our Discord server