From 8f849c39153e6c4e7ad64b8b75d87247813a7b3e Mon Sep 17 00:00:00 2001 From: jdalton Date: Fri, 6 Feb 2026 15:46:54 -0800 Subject: [PATCH] fix(sdk): correct endpoints and improve type safety MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix createOrgDiffScanFromIds endpoint URL (/diff-scans → /diff-scans/from-ids) and replace QueryParams with properly typed options (after, before, description, external_href, merge) - Add getDiffScanGfm method for /orgs/{org_slug}/diff-scans/{diff_scan_id}/gfm endpoint - Add getSupportedFiles method for /orgs/{org_slug}/supported-files endpoint (non-deprecated) - Fix createRepository options type with specific fields instead of generic QueryParams - Split RepositoryItem type: RepositoryListItem (for list endpoint) and RepositoryItem (for get endpoint) to remove integration_meta and slig from list results where they're not available - Add unit tests for all new methods and updated signatures --- src/index.ts | 1 + src/socket-sdk-class.ts | 164 +++++++++++++++++- src/types-strict.ts | 26 ++- .../socket-sdk-api-methods.coverage.test.mts | 47 ++++- 4 files changed, 227 insertions(+), 11 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9bf09a02..0d89478c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -126,6 +126,7 @@ export type { RepositoryLabelResult, RepositoryLabelsListData, RepositoryLabelsListResult, + RepositoryListItem, RepositoryResult, StreamFullScanOptions, StrictErrorResult, diff --git a/src/socket-sdk-class.ts b/src/socket-sdk-class.ts index daa0a3d8..fb4bc745 100644 --- a/src/socket-sdk-class.ts +++ b/src/socket-sdk-class.ts @@ -1204,11 +1204,44 @@ export class SocketSdk { * Create a diff scan from two full scan IDs. * Compares two existing full scans to identify changes. * + * @param orgSlug - Organization identifier + * @param options - Diff scan creation options + * @param options.after - ID of the after/head full scan (newer) + * @param options.before - ID of the before/base full scan (older) + * @param options.description - Description of the diff scan + * @param options.external_href - External URL to associate with the diff scan + * @param options.merge - Set true for merged commits, false for open PR diffs + * @returns Diff scan details + * + * @example + * ```typescript + * const result = await sdk.createOrgDiffScanFromIds('my-org', { + * before: 'scan-id-1', + * after: 'scan-id-2', + * description: 'Compare versions', + * merge: false + * }) + * + * if (result.success) { + * console.log('Diff scan created:', result.data.diff_scan.id) + * } + * ``` + * + * @see https://docs.socket.dev/reference/createorgdiffscanfromids + * @apiEndpoint POST /orgs/{org_slug}/diff-scans/from-ids + * @quota 1 unit + * @scopes diff-scans:create, full-scans:list * @throws {Error} When server returns 5xx status codes */ async createOrgDiffScanFromIds( orgSlug: string, - queryParams?: QueryParams | undefined, + options: { + after: string + before: string + description?: string | undefined + external_href?: string | undefined + merge?: boolean | undefined + }, ): Promise> { try { const data = await this.#executeWithRetry( @@ -1217,7 +1250,7 @@ export class SocketSdk { await createRequestWithJson( 'POST', this.#baseUrl, - `orgs/${encodeURIComponent(orgSlug)}/diff-scans?${queryToSearchParams(queryParams)}`, + `orgs/${encodeURIComponent(orgSlug)}/diff-scans/from-ids?${queryToSearchParams(options)}`, {}, { ...this.#reqOptions, hooks: this.#hooks }, ), @@ -1338,7 +1371,14 @@ export class SocketSdk { * Registers a repository for monitoring and security scanning. * * @param orgSlug - Organization identifier - * @param params - Repository configuration (name, description, homepage, etc.) + * @param params - Repository configuration + * @param params.archived - Whether the repository is archived + * @param params.default_branch - Default branch of the repository + * @param params.description - Description of the repository + * @param params.homepage - Homepage URL of the repository + * @param params.name - Name of the repository + * @param params.visibility - Visibility setting ('public' or 'private') + * @param params.workspace - Workspace of the repository * @returns Created repository details * * @example @@ -1346,7 +1386,8 @@ export class SocketSdk { * const result = await sdk.createRepository('my-org', { * name: 'my-repo', * description: 'My project repository', - * homepage: 'https://example.com' + * homepage: 'https://example.com', + * visibility: 'private' * }) * * if (result.success) { @@ -1362,7 +1403,17 @@ export class SocketSdk { */ async createRepository( orgSlug: string, - params?: QueryParams | undefined, + params?: + | { + archived?: boolean | undefined + default_branch?: null | string | undefined + description?: null | string | undefined + homepage?: null | string | undefined + name?: string | undefined + visibility?: 'private' | 'public' | undefined + workspace?: string | undefined + } + | undefined, ): Promise { try { const data = await this.#executeWithRetry( @@ -2187,6 +2238,56 @@ export class SocketSdk { /* c8 ignore stop */ } + /** + * Get GitHub-flavored markdown comments for a diff scan. + * Returns dependency overview and alert comments suitable for pull requests. + * + * @param orgSlug - Organization identifier + * @param diffScanId - Diff scan identifier + * @param options - Optional query parameters + * @param options.github_installation_id - GitHub installation ID for settings + * @returns Diff scan metadata with formatted markdown comments + * + * @example + * ```typescript + * const result = await sdk.getDiffScanGfm('my-org', 'diff-scan-id') + * + * if (result.success) { + * console.log(result.data.dependency_overview_comment) + * console.log(result.data.dependency_alert_comment) + * } + * ``` + * + * @see https://docs.socket.dev/reference/getdiffscangfm + * @apiEndpoint GET /orgs/{org_slug}/diff-scans/{diff_scan_id}/gfm + * @quota 1 unit + * @scopes diff-scans:list + * @throws {Error} When server returns 5xx status codes + */ + async getDiffScanGfm( + orgSlug: string, + diffScanId: string, + options?: { github_installation_id?: string | undefined } | undefined, + ): Promise> { + try { + const data = await this.#executeWithRetry( + async () => + await getResponseJson( + await createGetRequest( + this.#baseUrl, + `orgs/${encodeURIComponent(orgSlug)}/diff-scans/${encodeURIComponent(diffScanId)}/gfm${options ? `?${queryToSearchParams(options)}` : ''}`, + { ...this.#reqOptions, hooks: this.#hooks }, + ), + ), + ) + return this.#handleApiSuccess<'GetDiffScanGfm'>(data) + /* c8 ignore start - Standard API error handling, tested via public method error cases */ + } catch (e) { + return await this.#handleApiError<'GetDiffScanGfm'>(e) + } + /* c8 ignore stop */ + } + /** * Retrieve the enabled entitlements for an organization. * @@ -3001,10 +3102,63 @@ export class SocketSdk { /* c8 ignore stop */ } + /** + * Get list of supported file types for full scan generation. + * Returns glob patterns for supported manifest files, lockfiles, and configuration formats. + * + * Files whose names match the patterns returned by this endpoint can be uploaded + * for report generation. Examples include `package.json`, `package-lock.json`, and `yarn.lock`. + * + * @param orgSlug - Organization identifier + * @returns Nested object with environment and file type patterns + * + * @example + * ```typescript + * const result = await sdk.getSupportedFiles('my-org') + * + * if (result.success) { + * console.log('NPM patterns:', result.data.NPM) + * console.log('PyPI patterns:', result.data.PyPI) + * } + * ``` + * + * @see https://docs.socket.dev/reference/getsupportedfiles + * @apiEndpoint GET /orgs/{org_slug}/supported-files + * @quota 1 unit + * @scopes No scopes required, but authentication is required + * @throws {Error} When server returns 5xx status codes + */ + async getSupportedFiles( + orgSlug: string, + ): Promise> { + try { + const data = await this.#executeWithRetry( + async () => + await getResponseJson( + await createGetRequest( + this.#baseUrl, + `orgs/${encodeURIComponent(orgSlug)}/supported-files`, + { + ...this.#reqOptions, + hooks: this.#hooks, + }, + ), + ), + ) + return this.#handleApiSuccess<'getSupportedFiles'>(data) + /* c8 ignore start - Standard API error handling, tested via public method error cases */ + } catch (e) { + return await this.#handleApiError<'getSupportedFiles'>(e) + } + /* c8 ignore stop */ + } + /** * Get list of file types and formats supported for scanning. * Returns supported manifest files, lockfiles, and configuration formats. * + * @deprecated Use getSupportedFiles() instead. This endpoint has been deprecated + * since 2023-01-15 and now uses the /report/supported endpoint. * @throws {Error} When server returns 5xx status codes */ async getSupportedScanFiles(): Promise< diff --git a/src/types-strict.ts b/src/types-strict.ts index eba85d36..66d7a07c 100644 --- a/src/types-strict.ts +++ b/src/types-strict.ts @@ -120,16 +120,36 @@ export type OrganizationItem = { slug: string } +/** + * Strict type for repository list item. + * Used in list repositories endpoint - excludes fields only available in get repository. + */ +export type RepositoryListItem = { + archived: boolean + created_at: string + default_branch: string | null + description: string | null + head_full_scan_id: string | null + homepage: string | null + id: string + name: string + slug: string + updated_at: string + visibility: 'public' | 'private' + workspace: string +} + /** * Strict type for repositories list data. */ export type RepositoriesListData = { nextPage?: number | null | undefined - results: RepositoryItem[] + results: RepositoryListItem[] } /** - * Strict type for repository item. + * Strict type for single repository item. + * Used in get repository endpoint - includes all fields including integration_meta and slig. */ export type RepositoryItem = { archived: boolean @@ -166,7 +186,7 @@ export type RepositoryItem = { } } | null name: string - slig?: string | undefined + slig: string slug: string updated_at: string visibility: 'public' | 'private' diff --git a/test/unit/socket-sdk-api-methods.coverage.test.mts b/test/unit/socket-sdk-api-methods.coverage.test.mts index 1c7fbb20..4416a112 100644 --- a/test/unit/socket-sdk-api-methods.coverage.test.mts +++ b/test/unit/socket-sdk-api-methods.coverage.test.mts @@ -491,6 +491,19 @@ describe('SocketSdk - API Methods Coverage', () => { expect(result.success).toBe(true) }) + it('covers createRepository with all options', async () => { + const result = await client.createRepository('test-org', { + archived: false, + default_branch: 'main', + description: 'Test repository', + homepage: 'https://example.com', + name: 'test-repo', + visibility: 'private', + workspace: 'default', + }) + expect(result.success).toBe(true) + }) + it('covers getRepository', async () => { const result = await client.getRepository('test-org', 'test-repo') expect(result.success).toBe(true) @@ -555,8 +568,19 @@ describe('SocketSdk - API Methods Coverage', () => { describe('Diff Scan Methods', () => { it('covers createOrgDiffScanFromIds', async () => { const result = await client.createOrgDiffScanFromIds('test-org', { - from: 'from-id', - to: 'to-id', + after: 'after-id', + before: 'before-id', + }) + expect(result.success).toBe(true) + }) + + it('covers createOrgDiffScanFromIds with all options', async () => { + const result = await client.createOrgDiffScanFromIds('test-org', { + after: 'after-id', + before: 'before-id', + description: 'Compare versions', + external_href: 'https://github.com/org/repo/pull/123', + merge: false, }) expect(result.success).toBe(true) }) @@ -566,6 +590,18 @@ describe('SocketSdk - API Methods Coverage', () => { expect(result.success).toBe(true) }) + it('covers getDiffScanGfm', async () => { + const result = await client.getDiffScanGfm('test-org', 'diff-1') + expect(result.success).toBe(true) + }) + + it('covers getDiffScanGfm with options', async () => { + const result = await client.getDiffScanGfm('test-org', 'diff-1', { + github_installation_id: 'install-123', + }) + expect(result.success).toBe(true) + }) + it('covers listOrgDiffScans', async () => { const result = await client.listOrgDiffScans('test-org') expect(result.success).toBe(true) @@ -1026,7 +1062,12 @@ describe('SocketSdk - API Methods Coverage', () => { }) describe('Supported Files Methods', () => { - it('covers getSupportedScanFiles', async () => { + it('covers getSupportedFiles', async () => { + const result = await client.getSupportedFiles('test-org') + expect(result.success).toBe(true) + }) + + it('covers getSupportedScanFiles (deprecated)', async () => { const result = await client.getSupportedScanFiles() expect(result.success).toBe(true) })