deepsource-mcp-server
Version:
Model Context Protocol server for DeepSource
1,159 lines (1,158 loc) • 45.9 kB
TypeScript
import { MetricShortcode, MetricKey, MetricThresholdStatus, MetricDirection, RepositoryMetric, RepositoryMetricItem, MetricSetting, UpdateMetricThresholdParams, UpdateMetricSettingParams, MetricThresholdUpdateResponse, MetricSettingUpdateResponse, MetricHistoryParams, MetricHistoryResponse, MetricHistoryValue } from './types/metrics.js';
import { GraphQLNodeId, RunId, CommitOid, BranchName, AnalyzerShortcode } from './types/branded.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: AnalyzerShortcode;
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: GraphQLNodeId;
runUid: RunId;
commitOid: CommitOid;
branchName: BranchName;
baseOid: CommitOid;
status: AnalysisRunStatus;
createdAt: string;
updatedAt: string;
finishedAt?: string;
summary: RunSummary;
repository: {
name: string;
id: GraphQLNodeId;
};
}
/**
* 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;
}