Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 67x 78x 9x 68x 68x 8x 60x 4x 56x 60x 9x 62x 62x 9x 59x 9x 15x 4x 11x 11x 1x 10x 3x 7x 7x 1x 6x | /** * Smart project identifier handling utilities * Handles both numeric IDs and namespace paths (URL-encoded or not) */ /** * Smart project identifier that can be numeric ID or namespace path */ export interface ProjectIdentifier { /** The normalized project identifier for API calls */ identifier: string; /** Whether this is a numeric ID (true) or namespace path (false) */ isNumericId: boolean; /** Original input value */ originalValue: string; } /** * Detects if a string is URL-encoded by checking for common encoded characters */ function isUrlEncoded(str: string): boolean { // Check for common URL encoded patterns: %20, %2F, %3A, etc. return /%[0-9A-Fa-f]{2}/.test(str); } /** * Detects if a string is a numeric ID */ function isNumericId(str: string): boolean { return /^\d+$/.test(str.trim()); } /** * Smart processing of project identifier that handles: * - Numeric IDs: "123" -> stays as "123" * - URL-encoded paths: "group%2Fproject" -> stays as "group%2Fproject" (for API) * - Regular paths: "group/project" -> converts to "group%2Fproject" * - Already properly encoded paths: detected and preserved */ export function processProjectIdentifier(input: string): ProjectIdentifier { const trimmedInput = input.trim(); // Check if it's a numeric ID if (isNumericId(trimmedInput)) { return { identifier: trimmedInput, isNumericId: true, originalValue: input, }; } // For namespace paths, we need to ensure proper encoding for GitLab API let identifier: string; if (isUrlEncoded(trimmedInput)) { // Already URL-encoded, use as-is (avoid double encoding) identifier = trimmedInput; } else { // Regular path, needs URL encoding identifier = encodeURIComponent(trimmedInput); } return { identifier, isNumericId: false, originalValue: input, }; } /** * Safe URL component encoding that avoids double-encoding * If input is already encoded, returns as-is * If input needs encoding, applies encodeURIComponent */ export function safeEncodeProjectId(projectId: string): string { const processed = processProjectIdentifier(projectId); return processed.identifier; } /** * Normalize project identifier for API calls * Ensures the identifier is properly formatted for GitLab REST API */ export function normalizeProjectId(projectId: string): string { return safeEncodeProjectId(projectId); } /** * Validate project identifier format * Returns error message if invalid, null if valid */ export function validateProjectIdentifier(input: string): string | null { if (!input || typeof input !== "string") { return "Project identifier is required and must be a string"; } const trimmed = input.trim(); if (trimmed.length === 0) { return "Project identifier cannot be empty"; } // Check if it's numeric ID if (isNumericId(trimmed)) { return null; // Valid numeric ID } // Check if it's a valid namespace path (with or without encoding) const decoded = isUrlEncoded(trimmed) ? decodeURIComponent(trimmed) : trimmed; // Basic validation for namespace/project format if (!/^[a-zA-Z0-9\-_./]+$/.test(decoded)) { return "Invalid project identifier format. Use numeric ID or namespace/project path."; } return null; // Valid } |