/** * @file 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/types'; import type { RequestOptions as HttpRequestOptions } from 'node:http'; import type { ClientSessionRequestOptions } from 'node:http2'; import type { 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 | undefined; }; export type Vulnerability = { cves: string[]; description: string; severity: string; summary: string; }; export type SecurityAlert = { description: string; severity: string; summary: string; cveId?: string | null | undefined; ghsaId?: string | null | undefined; }; 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 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 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; data: OpReturnType; error?: undefined; status: number; success: true; }; export type SocketSdkErrorResult = { cause?: string | undefined; data?: 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; data: T; error?: undefined; status: number; success: true; } | { cause?: string | undefined; data?: 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. * * @since V3.0.0 * * @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 */ 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 { /** * 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; /** * Delay in milliseconds between polls when a cached scan endpoint * (getDiffScanById, getFullScan) returns 202 Accepted (default: 2000). On a * cache miss the API computes the result in the background and the SDK polls * until it is ready. */ pollIntervalMs?: number | 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; /** * User-Agent token appended to the SDK's base User-Agent (which already * carries the SDK name/version, Node.js version, and OS platform/arch). */ userAgent?: string | undefined; } export type UploadManifestFilesResponse = { tarHash: string; unmatchedFiles: string[]; }; export type UploadManifestFilesReturnType = { cause?: undefined; data: UploadManifestFilesResponse; error?: undefined; status: 200; success: true; }; export type UploadManifestFilesError = { cause?: string | undefined; data?: undefined; error: string; status: number; success: false; }; export type BatchPackageFetchResultType = SocketSdkResult<'batchPackageFetch'>; export type BatchPackageStreamOptions = { /** * Components per request. Defaults to 1024 (the API's per-request max); * quota is charged per request, so the default is also the cheapest. */ 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; };