/** * @fileoverview Type definitions and interfaces for Socket SDK. * Provides TypeScript types for API requests, responses, and internal SDK functionality. */ import type { components, operations } from '../types/api'; import type { OpReturnType } from '../types/api-helpers'; import type { Remap } from '@socketsecurity/lib/objects'; import type { Agent as HttpAgent, RequestOptions as HttpRequestOptions } from 'node:http'; import type { ClientHttp2Session, ClientSessionRequestOptions } from 'node:http2'; import type { Agent as HttpsAgent, RequestOptions as HttpsRequestOptions } from 'node:https'; export type ALERT_ACTION = 'error' | 'monitor' | 'warn' | 'ignore'; export type ALERT_TYPE = keyof NonNullable; export type Entitlement = { enabled: boolean; key: string; }; export type EntitlementsResponse = { items: Entitlement[]; }; export type PatchFile = { afterHash?: string | undefined; beforeHash?: string | undefined; socketBlob?: string | null; }; export type Vulnerability = { cves: string[]; description: string; severity: string; summary: string; }; export type SecurityAlert = { description: string; severity: string; summary: string; cveId?: string | null; ghsaId?: string | null; }; export type PatchRecord = { description: string; license: string; publishedAt: string; securityAlerts: SecurityAlert[]; tier: 'free' | 'paid'; uuid: string; }; export type PatchViewResponse = { description: string; files: Record; license: string; publishedAt: string; purl: string; tier: 'free' | 'paid'; uuid: string; vulnerabilities: Record; }; export type ArtifactPatches = { artifactId: string; patches: PatchRecord[]; }; export type Agent = HttpsAgent | HttpAgent | ClientHttp2Session; export interface RequestInfo { method: string; url: string; headers?: Record | undefined; timeout?: number | undefined; } export interface ResponseInfo { method: string; url: string; duration: number; status?: number | undefined; statusText?: string | undefined; headers?: Record | undefined; error?: Error | undefined; } export type CompactSocketArtifactAlert = Remap>; export type CompactSocketArtifact = Remap & { alerts: CompactSocketArtifactAlert[]; }>; export type CustomResponseType = 'response' | 'text' | 'json'; export type GetOptions = { responseType?: CustomResponseType | undefined; throws?: boolean | undefined; }; export type GotOptions = { http2?: ClientHttp2Session | undefined; http?: HttpAgent | undefined; https?: HttpsAgent | undefined; }; export type QueryParams = Record; export type HeadersRecord = Record | undefined; export type SocketMetricSchema = components['schemas']['SocketMetricSchema']; export type SocketId = components['schemas']['SocketId']; export type SocketArtifactWithExtras = SocketArtifact & { scorecards?: unknown | undefined; supplyChainRisk?: SocketMetricSchema | undefined; topLevelAncestors?: SocketId[] | undefined; }; export type RequestOptions = ((HttpsRequestOptions & { headers?: HeadersRecord | undefined; }) | (HttpRequestOptions & { headers?: HeadersRecord | undefined; }) | (ClientSessionRequestOptions & { headers?: HeadersRecord | undefined; })) & { timeout?: number | undefined; }; export type RequestOptionsWithHooks = RequestOptions & { hooks?: { onRequest?: ((info: RequestInfo) => void) | undefined; onResponse?: ((info: ResponseInfo) => void) | undefined; } | undefined; }; export type SendMethod = 'POST' | 'PUT'; export type SendOptions = { body?: unknown | undefined; method?: SendMethod | undefined; throws?: boolean | undefined; }; export type SocketArtifact = Remap & { alerts?: SocketArtifactAlert[] | undefined; }>; export type SocketArtifactAlert = Remap & { type: ALERT_TYPE; action?: ALERT_ACTION | undefined; props?: Record | undefined; }>; export type SocketSdkOperations = keyof operations; export type SocketSdkSuccessResult = { cause?: undefined | undefined; data: OpReturnType; error?: undefined | undefined; status: number; success: true; }; export type SocketSdkErrorResult = { cause?: string | undefined; data?: undefined | undefined; error: string; status: number; success: false; url?: string | undefined; _operation?: T | undefined; }; export type SocketSdkResult = SocketSdkSuccessResult | SocketSdkErrorResult; /** * Helper type to extract the data from a successful SDK operation result. * @example * type RepoData = SocketSdkData<'getOrgRepoList'> */ export type SocketSdkData = OpReturnType; /** * Helper type to extract array element type from SDK operation results. * Useful for typing items from paginated results. * @example * type RepoItem = SocketSdkArrayElement<'getOrgRepoList', 'results'> */ export type SocketSdkArrayElement> = SocketSdkData[K] extends Array ? U : never; export type SocketSdkGenericResult = { cause?: undefined | undefined; data: T; error?: undefined | undefined; status: number; success: true; } | { cause?: string | undefined; data?: undefined | undefined; error: string; status: number; success: false; url?: string | undefined; }; export type MalwareCheckAlert = { category?: string | undefined; fix?: { description: string; type: string; } | undefined; key: string; props?: Record | undefined; severity?: string | undefined; type: ALERT_TYPE; }; export type MalwareCheckPackage = { alerts: MalwareCheckAlert[]; name?: string | undefined; namespace?: string | undefined; score?: MalwareCheckScore | undefined; type: string; version?: string | undefined; }; export type MalwareCheckResult = MalwareCheckPackage[]; export type MalwareCheckScore = { license: number; maintenance: number; overall: number; quality: number; supplyChain: number; vulnerability: number; }; /** * Result from file validation callback. * Allows consumers to customize error handling and logging. * * @since v3.0.0 */ export interface FileValidationResult { /** * Whether to continue with the operation using valid files. * If false, the SDK operation will fail with the provided error message. */ shouldContinue: boolean; /** * Optional custom error message if shouldContinue is false. * If not provided, SDK will use default error message. */ errorMessage?: string | undefined; /** * Optional cause/reason for the error. */ errorCause?: string | undefined; } /** * Callback invoked when file validation detects unreadable files. * Gives consumers control over error messages and logging. * * @param validPaths - Files that passed validation (readable) * @param invalidPaths - Files that failed validation (unreadable) * @param context - Context about the operation (method name, orgSlug, etc.) * @returns Decision on whether to continue and optional custom error messages * * @since v3.0.0 */ export type FileValidationCallback = (validPaths: string[], invalidPaths: string[], context: { operation: 'createDependenciesSnapshot' | 'createFullScan' | 'uploadManifestFiles'; orgSlug?: string | undefined; [key: string]: unknown; }) => FileValidationResult | Promise; /** * Configuration options for SocketSdk. */ export interface SocketSdkOptions { /** HTTP agent for connection pooling and proxy support */ agent?: Agent | GotOptions | undefined; /** Base URL for Socket API (default: 'https://api.socket.dev/v0/') */ baseUrl?: string | undefined; /** * Enable TTL caching for API responses (default: false). * When enabled, GET requests are cached with configurable TTLs. * Only applies to listOrganizations() and getQuota() methods. */ cache?: boolean | undefined; /** * Cache TTL in milliseconds (default: 300_000 = 5 minutes). * Only used when cache is enabled. * Can be a single number for all endpoints or an object for per-endpoint TTLs. * * Recommended TTLs by endpoint: * - organizations: 30 minutes (rarely changes) * - quota: 10 minutes (changes incrementally) * * @example * // Single TTL for all endpoints. * cacheTtl: 15 * 60 * 1000 // 15 minutes * * @example * // Per-endpoint TTLs with recommended values. * cacheTtl: { * default: 5 * 60 * 1000, // 5 minutes default * organizations: 30 * 60 * 1000, // 30 minutes (recommended) * quota: 10 * 60 * 1000 // 10 minutes (recommended) * } */ cacheTtl?: number | { default?: number | undefined; organizations?: number | undefined; quota?: number | undefined; } | undefined; /** * Callback for file validation events. * Called when any file-upload method detects unreadable files: * - createDependenciesSnapshot * - createFullScan (formerly createOrgFullScan) * - uploadManifestFiles * * Default behavior (if not provided): * - Warns about invalid files (console.warn) * - Continues with valid files if any exist * - Throws error if all files are invalid * * @since v3.0.0 */ onFileValidation?: FileValidationCallback | undefined; /** Request/response logging hooks */ hooks?: { onRequest?: ((info: RequestInfo) => void) | undefined; onResponse?: ((info: ResponseInfo) => void) | undefined; } | undefined; /** * Number of retry attempts on failure (default: 3). * Uses exponential backoff between retries. */ retries?: number | undefined; /** * Initial delay in milliseconds between retries (default: 1000). * Uses exponential backoff: 1000ms, 2000ms, 4000ms, etc. */ retryDelay?: number | undefined; /** Request timeout in milliseconds */ timeout?: number | undefined; /** Custom User-Agent header */ userAgent?: string | undefined; } export type UploadManifestFilesResponse = { tarHash: string; unmatchedFiles: string[]; }; export type UploadManifestFilesReturnType = { cause?: undefined | undefined; data: UploadManifestFilesResponse; error?: undefined | undefined; status: 200; success: true; }; export type UploadManifestFilesError = { cause?: string | undefined; data?: undefined | undefined; error: string; status: number; success: false; }; export type BatchPackageFetchResultType = SocketSdkResult<'batchPackageFetch'>; export type BatchPackageStreamOptions = { chunkSize?: number | undefined; concurrencyLimit?: number | undefined; queryParams?: QueryParams | undefined; }; export type CreateDependenciesSnapshotOptions = { pathsRelativeTo?: string | undefined; queryParams?: QueryParams | undefined; }; export type StreamOrgFullScanOptions = { output?: boolean | string | undefined; }; export type PostOrgTelemetryPayload = Record; export type PostOrgTelemetryResponse = Record; /** * Configuration for telemetry collection. * Controls whether telemetry is enabled and how events are collected. */ export interface TelemetryConfig { telemetry: { enabled: boolean; }; } export type UploadManifestFilesOptions = { pathsRelativeTo?: string | undefined; };