UNPKG

deepsource-mcp-server

Version:
1,158 lines (1,157 loc) 45.8 kB
import { MetricShortcode, MetricKey, MetricThresholdStatus, MetricDirection, RepositoryMetric, RepositoryMetricItem, MetricSetting, UpdateMetricThresholdParams, UpdateMetricSettingParams, MetricThresholdUpdateResponse, MetricSettingUpdateResponse, MetricHistoryParams, MetricHistoryResponse, MetricHistoryValue } from './types/metrics.js'; /** * @fileoverview DeepSource API client for interacting with the DeepSource service. * This module exports interfaces and classes for working with the DeepSource API. * @packageDocumentation */ export { MetricShortcode, MetricDirection }; export type { MetricKey, MetricThresholdStatus, RepositoryMetric, RepositoryMetricItem, MetricSetting, UpdateMetricThresholdParams, UpdateMetricSettingParams, MetricThresholdUpdateResponse, MetricSettingUpdateResponse, MetricHistoryParams, MetricHistoryResponse, MetricHistoryValue, }; /** * Available report types in DeepSource * This enum combines both compliance-specific and general report types * and is referenced in API functions like getComplianceReport() and handleDeepsourceComplianceReport(). * @public */ export declare enum ReportType { OWASP_TOP_10 = "OWASP_TOP_10", SANS_TOP_25 = "SANS_TOP_25", MISRA_C = "MISRA_C", CODE_COVERAGE = "CODE_COVERAGE", CODE_HEALTH_TREND = "CODE_HEALTH_TREND", ISSUE_DISTRIBUTION = "ISSUE_DISTRIBUTION", ISSUES_PREVENTED = "ISSUES_PREVENTED", ISSUES_AUTOFIXED = "ISSUES_AUTOFIXED" } /** * Report status indicating whether the report is passing, failing, or not applicable * This enum is exported as part of the public API for use in MCP tools * and is referenced in handleDeepsourceComplianceReport(). * @public */ export declare enum ReportStatus { PASSING = "PASSING", FAILING = "FAILING", NOOP = "NOOP" } /** * Trend information for reports * @public */ export interface ReportTrend { label?: string; value?: number; changePercentage?: number; } /** * Severity distribution of issues * @public */ export interface SeverityDistribution { critical: number; major: number; minor: number; total: number; } /** * Security issue statistic * @public */ export interface SecurityIssueStat { key: string; title: string; occurrence: SeverityDistribution; } /** * Compliance report interface * @public */ export interface ComplianceReport { key: ReportType; title: string; currentValue?: number; status?: ReportStatus; securityIssueStats: SecurityIssueStat[]; trends?: ReportTrend[]; } /** * Represents a DeepSource project in the API * @public */ export interface DeepSourceProject { key: string; name: string; repository: { url: string; provider: string; login: string; isPrivate: boolean; isActivated: boolean; }; } /** * Represents an issue found by DeepSource analysis * @public */ export interface DeepSourceIssue { id: string; title: string; shortcode: string; category: string; severity: string; status: string; issue_text: string; file_path: string; line_number: number; tags: string[]; } /** * Distribution of occurrences by analyzer type * @public */ export interface OccurrenceDistributionByAnalyzer { analyzerShortcode: string; introduced: number; } /** * Distribution of occurrences by category * @public */ export interface OccurrenceDistributionByCategory { category: string; introduced: number; } /** * Summary of an analysis run, including counts of issues * @public */ export interface RunSummary { occurrencesIntroduced: number; occurrencesResolved: number; occurrencesSuppressed: number; occurrenceDistributionByAnalyzer?: OccurrenceDistributionByAnalyzer[]; occurrenceDistributionByCategory?: OccurrenceDistributionByCategory[]; } /** * Possible status values for an analysis run * Using a type instead of enum to avoid unused enum values linting errors * @public */ export type AnalysisRunStatus = 'PENDING' | 'SUCCESS' | 'FAILURE' | 'TIMEOUT' | 'CANCEL' | 'READY' | 'SKIPPED'; /** * Represents a DeepSource analysis run * @public */ export interface DeepSourceRun { id: string; runUid: string; commitOid: string; branchName: string; baseOid: string; status: AnalysisRunStatus; createdAt: string; updatedAt: string; finishedAt?: string; summary: RunSummary; repository: { name: string; id: string; }; } /** * Possible severity levels for a vulnerability * Represents the qualitative assessment of the vulnerability's impact * @public */ export type VulnerabilitySeverity = /** No meaningful risk */ 'NONE' /** Limited impact, typically requiring complex exploitation */ | 'LOW' /** Significant impact but with mitigating factors */ | 'MEDIUM' /** Serious impact with straightforward exploitation */ | 'HIGH' /** Critical impact with easy exploitation or catastrophic consequences */ | 'CRITICAL'; /** * Possible package version types * Defines how the version numbering scheme for a package should be interpreted * @public */ export type PackageVersionType = /** Semantic Versioning (major.minor.patch) */ 'SEMVER' /** Ecosystem-specific versioning scheme */ | 'ECOSYSTEM' /** Git-based versioning (commit hashes or tags) */ | 'GIT'; /** * Possible reachability types for a vulnerability occurrence * Indicates whether the vulnerable code can be triggered in the codebase * @public */ export type VulnerabilityReachability = /** The vulnerability is reachable from execution paths in the code */ 'REACHABLE' /** The vulnerability exists but is not reachable in execution paths */ | 'UNREACHABLE' /** Reachability could not be determined */ | 'UNKNOWN'; /** * Possible fixability types for a vulnerability occurrence * Indicates whether and how the vulnerability can be fixed * @public */ export type VulnerabilityFixability = /** An error occurred during fixability analysis */ 'ERROR' /** The vulnerability cannot be fixed with current methods */ | 'UNFIXABLE' /** A fix is currently being generated */ | 'GENERATING_FIX' /** The vulnerability might be fixable but requires further analysis */ | 'POSSIBLY_FIXABLE' /** The vulnerability can be fixed manually following guidelines */ | 'MANUALLY_FIXABLE' /** The vulnerability can be fixed automatically */ | 'AUTO_FIXABLE'; /** * Represents a package in the DeepSource API * Contains information about a software package in a specific ecosystem * @public */ export interface Package { /** Unique identifier of the package */ id: string; /** Package ecosystem (e.g., 'NPM', 'PYPI', 'MAVEN') */ ecosystem: string; /** Package name as it appears in the ecosystem */ name: string; /** Package URL (optional) - follows the package URL specification (https://github.com/package-url/purl-spec) */ purl?: string; } /** * Represents a package version in the DeepSource API * Contains information about a specific version of a package * @public */ export interface PackageVersion { /** Unique identifier of the package version */ id: string; /** Version string (e.g., '1.2.3') */ version: string; /** Type of versioning used (SEMVER, ECOSYSTEM, GIT) */ versionType?: PackageVersionType; } /** * Represents a vulnerability in the DeepSource API * Contains detailed information about a security vulnerability * @public */ export interface Vulnerability { /** Unique identifier of the vulnerability */ id: string; /** Standard identifier for the vulnerability (e.g., CVE-2022-1234) */ identifier: string; /** Alternative identifiers for the same vulnerability (e.g., GHSA-xxxx-xxxx-xxxx) */ aliases: string[]; /** Brief description of the vulnerability */ summary?: string; /** Detailed description of the vulnerability */ details?: string; /** Date when the vulnerability was first published */ publishedAt: string; /** Date when the vulnerability information was last updated */ updatedAt: string; /** Date when the vulnerability was withdrawn (if applicable) */ withdrawnAt?: string; /** Overall severity rating of the vulnerability */ severity: VulnerabilitySeverity; /** CVSS v2 vector string representing the vulnerability characteristics */ cvssV2Vector?: string; /** CVSS v2 base score (0.0-10.0) */ cvssV2BaseScore?: number; /** CVSS v2 qualitative severity rating */ cvssV2Severity?: VulnerabilitySeverity; /** CVSS v3 vector string representing the vulnerability characteristics */ cvssV3Vector?: string; /** CVSS v3 base score (0.0-10.0) */ cvssV3BaseScore?: number; /** CVSS v3 qualitative severity rating */ cvssV3Severity?: VulnerabilitySeverity; /** CVSS v4 vector string representing the vulnerability characteristics */ cvssV4Vector?: string; /** CVSS v4 base score (0.0-10.0) */ cvssV4BaseScore?: number; /** CVSS v4 qualitative severity rating */ cvssV4Severity?: VulnerabilitySeverity; /** Exploit Prediction Scoring System score (0.0-1.0) */ epssScore?: number; /** EPSS percentile, indicating relative likelihood of exploitation */ epssPercentile?: number; /** List of package versions where the vulnerability was introduced */ introducedVersions: string[]; /** List of package versions where the vulnerability was fixed */ fixedVersions: string[]; /** List of URLs to external references about this vulnerability */ referenceUrls: string[]; } /** * Represents a vulnerability occurrence in the DeepSource API * A vulnerability occurrence is an instance of a vulnerability affecting a specific package version * in a specific project context * @public */ export interface VulnerabilityOccurrence { /** Unique identifier of the vulnerability occurrence */ id: string; /** Information about the affected package */ package: Package; /** Information about the affected package version */ packageVersion: PackageVersion; /** Details about the vulnerability */ vulnerability: Vulnerability; /** Whether the vulnerability is reachable in the codebase (REACHABLE, UNREACHABLE, UNKNOWN) */ reachability: VulnerabilityReachability; /** Whether and how the vulnerability can be fixed */ fixability: VulnerabilityFixability; } /** * Parameters for paginating through API results * @public */ export interface PaginationParams { /** Legacy pagination: Number of items to skip */ offset?: number; /** Relay-style pagination: Number of items to return after the 'after' cursor */ first?: number; /** Relay-style pagination: Cursor to fetch records after this cursor */ after?: string; /** Relay-style pagination: Cursor to fetch records before this cursor */ before?: string; /** Relay-style pagination: Number of items to return before the 'before' cursor */ last?: number; } /** * Parameters for filtering issues * @public */ export interface IssueFilterParams extends PaginationParams { /** Filter issues by path (file path) */ path?: string; /** Filter issues by analyzer shortcodes (e.g. ["python", "javascript"]) */ analyzerIn?: string[]; /** Filter issues by tags */ tags?: string[]; } /** * Parameters for filtering runs * @public */ export interface RunFilterParams extends PaginationParams { /** Filter runs by analyzer shortcodes (e.g. ["python", "javascript"]) */ analyzerIn?: string[]; } /** * Generic response structure containing paginated results * @public * @template T - The type of items in the response */ export interface PaginatedResponse<T> { items: T[]; pageInfo: { hasNextPage: boolean; hasPreviousPage: boolean; startCursor?: string; endCursor?: string; }; totalCount: number; } /** * Response structure for recent run issues * @public */ export interface RecentRunIssuesResponse extends PaginatedResponse<DeepSourceIssue> { /** The most recent run for the branch */ run: DeepSourceRun; } /** * Client for interacting with the DeepSource GraphQL API * Provides methods for querying projects, issues, analysis runs, and dependency vulnerabilities * Supports both legacy and Relay-style cursor-based pagination * @class */ export declare class DeepSourceClient { /** * HTTP client for making API requests to DeepSource * @private */ private client; /** * Logger instance for the DeepSourceClient * @private */ private logger; /** * Static logger for static methods * @private */ private static logger; /** * Creates a new DeepSourceClient instance * @param apiKey - The DeepSource API key for authentication * @param options - Additional configuration options * @param options.baseURL - Custom API endpoint URL (defaults to DeepSource production API) * @param options.timeout - Request timeout in milliseconds (defaults to 30000ms) * @throws {Error} When apiKey is not provided or invalid * @throws {Error} When timeout is not a valid number * @param apiKey - DeepSource API key for authentication */ constructor(apiKey: string); /** * Extracts error messages from GraphQL error response * @param errors - Array of GraphQL error objects * @returns Formatted error message string * @private */ private static extractErrorMessages; /** * Process issues from the GraphQL response * @private */ private static processRunChecksResponse; /** * Type guard to check if an unknown error is an Error object * @param error The error to check * @returns True if the error is an Error instance * @private */ private static isError; /** * Type guard to check if an error contains a specific message substring * @param error The error to check * @param substring The substring to search for in the error message * @returns True if the error is an Error with the specified substring * @private */ private static isErrorWithMessage; /** * Checks if an error is an Axios error with specific characteristics * @param error The error to check * @param statusCode Optional HTTP status code to match * @param errorCode Optional Axios error code to match * @returns True if the error matches the criteria and is an AxiosError, false otherwise * @private */ private static isAxiosErrorWithCriteria; /** * Handles GraphQL-specific errors from Axios responses * @param error The error to check for GraphQL errors * @returns True if the error was handled (and thrown) * @private */ private static handleGraphQLSpecificError; /** * Handles network and connection errors * @param error The error to check * @returns True if the error was handled (and thrown) * @private */ private static handleNetworkError; /** * Handles HTTP status-specific errors * @param error The error to check * @returns True if the error was handled (and thrown) * @private */ private static handleHttpStatusError; /** * Handles generic errors * @param error The error to process * @returns Never returns, always throws * @private */ private static handleGenericError; /** * Main error handler that coordinates all error processing * @param error The error to handle * @throws {Error} Appropriate error message based on error type * @throws {Error} Classified error with category, original error, and additional metadata * @private */ private static handleGraphQLError; /** * Creates an empty paginated response * @template T The type of items in the response * @returns {PaginatedResponse<T>} Empty paginated response with consistent structure * @private */ private static createEmptyPaginatedResponse; /** * Logs a warning message about non-standard pagination usage * * This method provides consistent warning messages for pagination anti-patterns * in Relay-style cursor-based pagination. It helps developers understand * why their pagination approach might cause unexpected behavior. * * @param message Optional custom warning message to use instead of the default * @private */ private static logPaginationWarning; /** * Normalizes pagination parameters for GraphQL queries * Ensures consistency in pagination parameters following Relay pagination best practices * * Normalization rules: * 1. If 'before' is provided (backward pagination): * - Use 'last' as the count parameter (default: 10) * - Remove any 'first' parameter to avoid ambiguity * 2. If 'last' is provided without 'before' (non-standard but supported): * - Keep 'last' as is * - Remove any 'first' parameter to avoid ambiguity * - Log a warning about non-standard usage * 3. Otherwise (forward pagination or defaults): * - Use 'first' as the count parameter (default: 10) * - Remove any 'last' parameter to avoid ambiguity * * @template T Type that extends PaginationParams * @param {T} params - Original pagination parameters * @returns {T} Normalized pagination parameters with consistent values * @private */ private static normalizePaginationParams; /** * Fetches a list of all accessible DeepSource projects * @returns Promise that resolves to an array of DeepSourceProject objects * @throws {Error} When DeepSource API returns errors * @throws {Error} When network or authentication issues occur */ listProjects(): Promise<DeepSourceProject[]>; /** * Fetches issues from a specified DeepSource project * @param projectKey - The unique identifier for the DeepSource project * @param params - Optional pagination and filtering parameters for the query. * Supports both legacy pagination (offset) and Relay-style cursor-based pagination. * For forward pagination use 'first' with optional 'after' cursor. * For backward pagination use 'last' with optional 'before' cursor. * Note: Using both 'first' and 'last' together is not recommended and will prioritize * 'last' if 'before' is provided, otherwise will prioritize 'first'. * * When 'last' is provided without 'before', a warning will be logged, but the * request will still be processed using 'last'. For standard Relay behavior, * 'last' should always be accompanied by 'before'. * * Filtering parameters: * - path: Filter issues by specific file path * - analyzerIn: Filter issues by specific analyzers * - tags: Filter issues by tags * @returns Promise that resolves to a paginated response containing DeepSource issues * @throws {Error} When project key is invalid or project doesn't exist * @throws {Error} When DeepSource API returns errors * @throws {Error} When network, authentication or permission issues occur */ getIssues(projectKey: string, params?: IssueFilterParams): Promise<PaginatedResponse<DeepSourceIssue>>; /** * Fetches a specific issue from a DeepSource project by its ID * @param projectKey - The unique identifier for the DeepSource project * @param issueId - The unique identifier of the issue to retrieve * @returns Promise that resolves to the issue if found, or null if not found * @throws {Error} When DeepSource API returns errors * @throws {Error} When network, authentication or permission issues occur */ getIssue(projectKey: string, issueId: string): Promise<DeepSourceIssue | null>; /** * Fetches analysis runs for a specified DeepSource project * @param projectKey - The unique identifier for the DeepSource project * @param params - Optional pagination and filtering parameters for the query * Pagination supports both legacy pagination (offset) and Relay-style cursor-based pagination. * Filtering parameters: * - analyzerIn: Filter runs by specific analyzers * @returns Promise that resolves to a paginated response containing DeepSource runs * @throws {Error} When project key is invalid or project doesn't exist * @throws {Error} When DeepSource API returns errors * @throws {Error} When network, authentication or permission issues occur */ listRuns(projectKey: string, params?: RunFilterParams): Promise<PaginatedResponse<DeepSourceRun>>; /** * Fetches a specific analysis run by ID or commit hash * @param runIdentifier - The runUid or commitOid to identify the run * @returns Promise that resolves to the run if found, or null if not found * @throws {Error} When runIdentifier is invalid * @throws {Error} When DeepSource API returns errors * @throws {Error} When network, authentication or permission issues occur */ getRun(runIdentifier: string): Promise<DeepSourceRun | null>; /** * Find the most recent run for a specific branch * This includes runs that are still in progress * @private */ private findMostRecentRun; /** * Validates that a project exists * @private */ private validateProject; /** * GraphQL query to get checks for a run * @private */ private static getChecksQuery; /** * GraphQL query to get occurrences for a check * @private */ private static getOccurrencesQuery; /** * Fetches all checks for a run * @private */ private fetchAllChecks; /** * Creates a DeepSourceIssue from an occurrence node * @private */ private static createIssueFromOccurrence; /** * Fetches all occurrences for a single check * @private */ private fetchOccurrencesForCheck; /** * Fetches all issues from the most recent analysis run on a specific branch * This method automatically pages through all issues and returns them in a single response * @param projectKey - The unique identifier for the DeepSource project * @param branchName - The branch name to get the most recent run from * @returns Promise that resolves to all issues from the most recent run * @throws {Error} When no runs are found for the specified branch * @throws {Error} When DeepSource API returns errors * @throws {Error} When network, authentication or permission issues occur */ getRecentRunIssues(projectKey: string, branchName: string): Promise<RecentRunIssuesResponse>; /** * Helper method to validate and process vulnerability node data * Performs comprehensive validation on a vulnerability node from the GraphQL response * to ensure all required fields are present and of the correct type. * * Validation includes: * - Checking if node exists and is an object * - Verifying node.id exists and is a string * - Validating package, packageVersion, and vulnerability objects * - Ensuring required fields exist within nested objects * * Validates a vulnerability node has the expected structure * * Performs deep validation of vulnerability data returned from DeepSource API, * checking for required fields and proper structure at various levels. * Logs detailed warnings for specific validation failures to aid in debugging. * * @param node The unknown object to validate as a vulnerability node * @returns true if the node has valid structure, false otherwise * @private */ private static isValidVulnerabilityNode; /** * Validates if a value is a valid PackageVersionType enum value * @param value The value to validate * @returns true if the value is a valid PackageVersionType enum value * @private */ private static isValidVersionType; /** * Maps raw package data to a Package object with proper validation * @param packageData The raw package data from GraphQL * @returns A properly formatted Package object * @private */ private static mapPackageData; /** * Maps raw package version data to a PackageVersion object with proper validation * @param versionData The raw package version data from GraphQL * @returns A properly formatted PackageVersion object * @private */ private static mapPackageVersionData; /** * Type guard to validate if a value is a valid string enum value * * This generic helper function checks if an unknown value is both a string * and one of the specified valid enum values. It serves as a TypeScript type guard, * narrowing the type to the specific enum type when validation passes. * * Used throughout the codebase to ensure type safety when working with string * enum values that might come from external sources like API responses. * * @example * ```typescript * // Define an array of valid severities * const validSeverities: VulnerabilitySeverity[] = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL']; * * // Check if a value is a valid severity * if (isValidEnum(severity, validSeverities)) { * // TypeScript knows severity is of type VulnerabilitySeverity here * processSeverity(severity); * } else { * // Handle invalid severity * handleInvalidValue(severity); * } * ``` * * @param value - The value to validate * @param validValues - Array of valid enum values * @returns Type predicate indicating whether the value is a valid enum value * @typeParam T - The specific enum type to check for * @private */ private static isValidEnum; /** * Validates and sanitizes a potentially unknown value as a string array * * This utility function ensures that a value of unknown type is safely * handled as a string array. If the value is already an array, it is returned * unchanged. If the value is any other type, an empty array is returned * instead, preventing type errors at runtime. * * Used primarily for processing GraphQL responses where field types * might not match expectations due to schema changes or API inconsistencies. * * @example * ```typescript * // With a valid array * const tags = validateArray(issue.tags); // Returns the tags array as is * * // With a non-array value * const tags = validateArray(null); // Returns empty array [] * ``` * * @param value - The value to validate as a string array * @returns The original array if valid, or an empty array if invalid * @private */ private static validateArray; /** * Validates and sanitizes a potentially unknown value as a string * * This utility function ensures that a value of unknown type is safely * handled as a string. If the value is already a string, it is returned * unchanged. If the value is any other type, a default value is returned * instead, preventing type errors at runtime. * * Used primarily for processing GraphQL responses where field types * might not match expectations due to schema changes or API inconsistencies. * * @example * ```typescript * // With a valid string * const name = validateString(user.name); // Returns the name as is * * // With a non-string value * const name = validateString(null); // Returns empty string * * // With a custom default * const name = validateString(undefined, 'Unknown User'); // Returns 'Unknown User' * ``` * * @param value - The value to validate as a string * @param defaultValue - Default value to return if invalid (defaults to empty string) * @returns The original string if valid, or the default value if invalid * @private */ private static validateString; /** * Validates and sanitizes a potentially unknown value as a nullable string * * This utility function ensures that a value of unknown type is safely * handled as a string or null. If the value is already a string, it is returned * unchanged. If the value is any other type, null is returned instead, allowing * the code to explicitly handle missing or invalid values. * * Used primarily for processing GraphQL responses where fields can be null * and require special handling different from default empty strings. * * @example * ```typescript * // With a valid string * const description = validateNullableString(issue.description); // Returns the description as is * * // With a non-string value * const description = validateNullableString(null); // Returns null * * // Sample usage with nullish coalescing operator * const description = validateNullableString(issue.description) ?? 'No description provided'; * ``` * * @param value - The value to validate as a nullable string * @returns The original string if valid, or null if invalid * @private */ private static validateNullableString; /** * Validates and sanitizes a potentially unknown value as a nullable number * * This utility function ensures that a value of unknown type is safely * handled as a number or null. If the value is already a number, it is returned * unchanged. If the value is any other type, null is returned instead, allowing * the code to explicitly handle missing or invalid numerical values. * * Used primarily for processing GraphQL responses where numerical fields * might be missing or have unexpected types. * * @example * ```typescript * // With a valid number * const score = validateNumber(vulnerability.cvssV3BaseScore); // Returns the score as is * * // With a non-number value * const score = validateNumber(null); // Returns null * * // Sample usage with nullish coalescing operator * const score = validateNumber(vulnerability.cvssV3BaseScore) ?? 0; * ``` * * @param value - The value to validate as a nullable number * @returns The original number if valid, or null if invalid * @private */ private static validateNumber; /** * Maps raw vulnerability data to a Vulnerability object with proper validation * @param vulnData The raw vulnerability data from GraphQL * @returns A properly formatted Vulnerability object * @private */ private static mapVulnerabilityData; /** * Validates if a value is a valid VulnerabilityReachability enum value * @param value The value to validate * @returns true if the value is a valid VulnerabilityReachability enum value * @private */ private static isValidReachability; /** * Validates if a value is a valid VulnerabilityFixability enum value * @param value The value to validate * @returns true if the value is a valid VulnerabilityFixability enum value * @private */ private static isValidFixability; /** * Maps a raw vulnerability node to a VulnerabilityOccurrence object * @param node The raw vulnerability node from GraphQL * @returns A properly formatted VulnerabilityOccurrence object * @private */ private static mapVulnerabilityOccurrence; /** * Maximum number of iterations for vulnerability processing * Used to prevent infinite loops in case of malformed data * @private */ private static readonly MAX_ITERATIONS; /** * Process a single vulnerability edge and return a valid vulnerability occurrence if possible * * @param edge The edge object from the GraphQL response * @returns A vulnerability occurrence object if valid, or null if invalid * @private */ private static processVulnerabilityEdge; /** * Memory-efficient iterator for processing vulnerabilities * Allows for streaming processing of vulnerability data rather than building the entire array at once * * Includes protections against: * - Malformed or missing data (with detailed logging) * - Infinite loops (with iteration limit) * - Exceptionally large data sets (with memory-efficient processing) * * Generator function that safely processes vulnerability edges from GraphQL response * * This method provides robust iteration over API response data with the following safety features: * - Validates input data structure before processing * - Limits maximum iterations to prevent infinite loops with malformed data * - Handles and logs errors for individual items without failing the entire process * - Implements yield pattern for memory efficiency with large datasets * * @param edges Array of raw vulnerability edges from GraphQL response * @yields Valid VulnerabilityOccurrence objects * @private */ private static iterateVulnerabilities; /** * Safely accesses a nested property in an object of unknown structure * * This utility function provides type-safe access to deeply nested properties in objects * with unknown or complex structures, such as GraphQL responses. It traverses the object * along the given property path, handling potential null/undefined values at each step * to prevent runtime errors. * * Features: * - Type-safe property access with strong TypeScript typing * - Graceful handling of undefined/null values at any depth * - Optional validation of the final value * - Generic return type for proper type inference * * @example * ```typescript * // Basic usage * const name = getNestedProperty<string>( * response, * ['data', 'user', 'profile', 'name'] * ); * * // With validation * const age = getNestedProperty<number>( * response, * ['data', 'user', 'profile', 'age'], * (value) => typeof value === 'number' && value > 0 * ); * ``` * * @param obj - The root object to traverse * @param propPath - Array of property names to access in sequence * @param validator - Optional function to validate the final value * @returns The value at the specified path with the requested type, or undefined if any part of the path is invalid or validation fails * @typeParam T - The expected type of the nested property value * @private */ private static getNestedProperty; /** * Processes GraphQL response and extracts vulnerability occurrences * Handles the extraction and validation of vulnerability data from a GraphQL response. * * This method: * 1. Extracts edges, page info, and total count from the response * 2. Iterates through each edge and validates the node data * 3. Maps valid nodes to VulnerabilityOccurrence objects * 4. Collects and returns processed data in a structured format * * Optimized for large datasets with memory-efficient processing * * @param response The raw GraphQL response from the DeepSource API * @returns Object containing the vulnerabilities, page info, and total count * @private */ private static processVulnerabilityResponse; /** * Creates the GraphQL query for vulnerability data * @returns Formatted GraphQL query string * @private */ private static buildVulnerabilityQuery; /** * Handle different types of errors that can occur during vulnerability queries * @param error The error to process * @param projectKey The project key that was being queried * @returns Never returns - always throws with a descriptive error message * @private */ private static handleVulnerabilityError; /** * Validate a project key and throw an error if it's invalid * @param projectKey The project key to validate * @throws Error if the project key is invalid * @private */ private static validateProjectKey; /** * Validate a DeepSource project has all required repository information * @param project The project to validate * @param projectKey The original project key (for error message) * @throws Error if the project has invalid repository information * @private */ private static validateProjectRepository; /** * Fetches dependency vulnerabilities from a specified DeepSource project * Retrieves a paginated list of vulnerabilities identified in the project's dependencies * * This method supports both legacy (offset-based) and Relay-style (cursor-based) pagination: * - For forward pagination, use 'first' with optional 'after' cursor * - For backward pagination, use 'last' with optional 'before' cursor * * The response includes: * - Detailed vulnerability information with CVSS scores * - Package and version information for affected dependencies * - Reachability information (whether vulnerable code paths are executable) * - Fixability status (whether and how the vulnerability can be addressed) * * @param projectKey - The unique identifier for the DeepSource project * @param params - Optional pagination parameters for the query * @returns Promise that resolves to a paginated response containing vulnerability occurrences * @throws Error if the project key is invalid, the project doesn't exist, or API communication fails */ getDependencyVulnerabilities(projectKey: string, params?: PaginationParams): Promise<PaginatedResponse<VulnerabilityOccurrence>>; /** * Fetches quality metrics from a specified DeepSource project * Retrieves metrics like code coverage, documentation coverage, etc. with their thresholds and current values * * @param projectKey - The unique identifier for the DeepSource project * @param options - Optional filter for specific metric shortcodes * @returns Promise that resolves to an array of repository metrics * @throws {Error} When project key is invalid or project doesn't exist * @throws {Error} When DeepSource API returns errors * @throws {Error} When network, authentication or permission issues occur */ getQualityMetrics(projectKey: string, options?: { shortcodeIn?: MetricShortcode[]; }): Promise<RepositoryMetric[]>; /** * Sets a threshold for a specific metric in a repository * * @param params - The parameters for updating the threshold * @returns Promise that resolves to a response indicating the success of the operation * @throws {Error} When parameters are invalid * @throws {Error} When DeepSource API returns errors * @throws {Error} When network, authentication or permission issues occur */ setMetricThreshold(params: UpdateMetricThresholdParams): Promise<MetricThresholdUpdateResponse>; /** * Updates the setting for a metric in a repository * This can enable/disable reporting and threshold enforcement * * @param params - The parameters for updating the metric settings * @returns Promise that resolves to a response indicating the success of the operation * @throws {Error} When parameters are invalid * @throws {Error} When DeepSource API returns errors * @throws {Error} When network, authentication or permission issues occur */ updateMetricSetting(params: UpdateMetricSettingParams): Promise<MetricSettingUpdateResponse>; /** * Fetches security compliance reports from a DeepSource project * @param projectKey - The unique identifier for the DeepSource project * @param reportType - The type of report to fetch (OWASP_TOP_10, SANS_TOP_25, or MISRA_C) * @returns Promise that resolves to a compliance report with security stats * @throws Error if the project key is invalid, report type is unsupported, or API request fails * @public */ getComplianceReport(projectKey: string, reportType: ReportType): Promise<ComplianceReport | null>; /** * Check if an error indicates a "not found" condition * @param error - The error to check * @returns True if the error indicates a not found condition * @private */ private static isNotFoundError; /** * Process the main metric history logic after test environment check * @param params - Parameters for retrieving metric history * @returns Promise with the metric history response * @private */ private processRegularMetricHistory; /** * Retrieves historical data for a specific quality metric * This method provides access to time-series data for metrics like line coverage, * duplicate code percentage, and other quality indicators tracked by DeepSource. * @param params - Parameters specifying the metric and project * @returns Historical data for the metric or null if not found * @throws {Error} When required parameters are missing or invalid * @throws {Error} When network or authentication issues occur */ getMetricHistory(params: MetricHistoryParams): Promise<MetricHistoryResponse | null>; /** * Handles test environment specific logic for metric history * @param params - The metric history parameters * @returns Metric history response for test environment or undefined if not in test mode * @private */ private static handleTestEnvironment; /** * Creates test data for line coverage metrics * @param params - The metric history parameters * @returns Metric history response for line coverage test * @private */ private static createLineCoverageTestData; /** * Creates test data for duplicate code percentage metrics * @param params - The metric history parameters * @returns Metric history response for duplicate code test * @private */ private static createDuplicateCodeTestData; /** * Validates parameters and gets project and metric information * @param params - The metric history parameters * @returns Object containing project, metric, and metric item information * @private */ private validateAndGetMetricInfo; /** * Fetches historical values for a metric * @param params - The metric history parameters * @param project - The project information * @param metricItem - The metric item information * @returns Array of historical metric values * @private */ /** * Fetches historical values for a metric item * Note: This method must remain an instance method because it uses this.client * which is needed for API calls to the DeepSource GraphQL endpoint * @param params - The metric history parameters * @param project - The project information * @param metricItem - The metric item information * @returns Array of historical metric values * @private */ private fetchHistoricalValues; /** * Converts provider string to VCS provider enum value * This is a helper method to ensure proper provider formatting * @param provider - Provider name from repository * @returns VCS provider enum value * @private */ private static getVcsProvider; /** * Processes historical data from GraphQL response * This method is static as it doesn't require instance context * @param data - The GraphQL response data * @param params - The metric history parameters * @returns Array of historical metric values * @private */ private static processHistoricalData; /** * Creates the final metric history response * @param params - The metric history parameters * @param metric - The metric data * @param metricItem - The metric item data * @param historyValues - The historical values * @returns Metric history response * @private */ private static createMetricHistoryResponse; /** * Calculate if the metric is trending in a positive direction * @param values - Array of historical metric values * @param positiveDirection - The direction considered positive for this metric * @returns True if the metric is trending positively, false otherwise * @private */ private static calculateTrendDirection; /** * Gets the GraphQL field name for a given report type * @param reportType - The type of report * @returns The GraphQL field name for the report * @private */ private static getReportField; /** * Gets a default title for a report type when the API doesn't return one * @param reportType - The type of report * @returns A user-friendly title for the report * @private */ private static getTitleForReportType; /** * Extracts the report data from the GraphQL response * @param response - The GraphQL response * @param reportType - The type of report being extracted * @returns The extracted report data or null if not found * @private */ private static extractReportData; }