Skip to main content
Glama
MIT License
27,120
19,787
  • Linux
  • Apple
usePackRequest.ts•5.53 kB
import { computed, onMounted, ref } from 'vue'; import type { FileInfo, PackResult } from '../components/api/client'; import { handlePackRequest } from '../components/utils/requestHandlers'; import { isValidRemoteValue } from '../components/utils/validation'; import { parseUrlParameters } from '../utils/urlParams'; import { usePackOptions } from './usePackOptions'; export type InputMode = 'url' | 'file' | 'folder'; export function usePackRequest() { const packOptionsComposable = usePackOptions(); const { packOptions, getPackRequestOptions, resetOptions, applyUrlParameters, DEFAULT_PACK_OPTIONS } = packOptionsComposable; // Input states const inputUrl = ref(''); const inputRepositoryUrl = ref(''); const mode = ref<InputMode>('url'); const uploadedFile = ref<File | null>(null); // Request states const loading = ref(false); const error = ref<string | null>(null); const errorType = ref<'error' | 'warning'>('error'); const result = ref<PackResult | null>(null); const hasExecuted = ref(false); // Request controller for cancellation let requestController: AbortController | null = null; const TIMEOUT_MS = 30_000; // Computed validation const isSubmitValid = computed(() => { switch (mode.value) { case 'url': return !!inputUrl.value && isValidRemoteValue(inputUrl.value.trim()); case 'file': case 'folder': return !!uploadedFile.value; default: return false; } }); function setMode(newMode: InputMode) { mode.value = newMode; } function handleFileUpload(file: File) { uploadedFile.value = file; } function resetRequest() { error.value = null; errorType.value = 'error'; result.value = null; hasExecuted.value = false; } async function submitRequest() { if (!isSubmitValid.value) return; // Cancel any pending request if (requestController) { requestController.abort(); } requestController = new AbortController(); loading.value = true; error.value = null; errorType.value = 'error'; result.value = null; hasExecuted.value = true; inputRepositoryUrl.value = inputUrl.value; // Set up automatic timeout const timeoutId = setTimeout(() => { if (requestController) { requestController.abort('timeout'); } }, TIMEOUT_MS); try { await handlePackRequest( mode.value === 'url' ? inputUrl.value : '', packOptions.format, getPackRequestOptions.value, { onSuccess: (response) => { result.value = response; }, onError: (errorMessage) => { error.value = errorMessage; }, onAbort: (message) => { error.value = message; errorType.value = 'warning'; }, signal: requestController.signal, file: mode.value === 'file' || mode.value === 'folder' ? uploadedFile.value || undefined : undefined, }, ); } finally { clearTimeout(timeoutId); loading.value = false; requestController = null; } } async function repackWithSelectedFiles(selectedFiles: FileInfo[]) { if (!result.value || selectedFiles.length === 0) return; // Generate include patterns from selected files const selectedPaths = selectedFiles.map((file) => file.path); const includePatterns = selectedPaths.join(','); // Temporarily update pack options with include patterns const originalIncludePatterns = packOptions.includePatterns; const originalIgnorePatterns = packOptions.ignorePatterns; packOptions.includePatterns = includePatterns; packOptions.ignorePatterns = ''; // Clear ignore patterns to ensure selected files are included try { // Use the same loading state as normal pack processing await submitRequest(); // Update file selection state in the new result if (result.value?.metadata?.allFiles) { for (const file of result.value.metadata.allFiles) { file.selected = selectedPaths.includes(file.path); } } } finally { // Restore original pack options packOptions.includePatterns = originalIncludePatterns; packOptions.ignorePatterns = originalIgnorePatterns; } } function cancelRequest() { if (requestController) { requestController.abort('cancel'); requestController = null; } loading.value = false; } // Apply URL parameters after component mounts // This must be done here (not during setup) because during SSR/hydration, // browser globals like `window.location.search` are not available. // Accessing them before mounting would cause errors in SSR environments. onMounted(() => { const urlParams = parseUrlParameters(); // Apply pack options from URL parameters applyUrlParameters(urlParams); // Apply repo URL from URL parameters if (urlParams.repo) { inputUrl.value = urlParams.repo; } }); return { // Pack options (re-exported for convenience) ...packOptionsComposable, // Input states inputUrl, inputRepositoryUrl, mode, uploadedFile, // Request states loading, error, errorType, result, hasExecuted, // Computed isSubmitValid, // Actions setMode, handleFileUpload, resetRequest, submitRequest, repackWithSelectedFiles, cancelRequest, // Pack option actions resetOptions, DEFAULT_PACK_OPTIONS, }; }

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