@socketsecurity/sdk 1.8.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1342 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SocketSdk = void 0;
7
- /**
8
- * @fileoverview SocketSdk class implementation for Socket security API client.
9
- * Provides complete API functionality for vulnerability scanning, analysis, and reporting.
10
- */
11
- const node_events_1 = __importDefault(require("node:events"));
12
- const node_fs_1 = require("node:fs");
13
- const node_readline_1 = __importDefault(require("node:readline"));
14
- const abort_signal_1 = __importDefault(require("@socketsecurity/registry/lib/constants/abort-signal"));
15
- const socket_public_api_token_1 = __importDefault(require("@socketsecurity/registry/lib/constants/socket-public-api-token"));
16
- const unknown_error_1 = __importDefault(require("@socketsecurity/registry/lib/constants/unknown-error"));
17
- const debug_1 = require("@socketsecurity/registry/lib/debug");
18
- const json_1 = require("@socketsecurity/registry/lib/json");
19
- const objects_1 = require("@socketsecurity/registry/lib/objects");
20
- const promises_1 = require("@socketsecurity/registry/lib/promises");
21
- const url_1 = require("@socketsecurity/registry/lib/url");
22
- const constants_1 = require("./constants");
23
- const file_upload_1 = require("./file-upload");
24
- const http_client_1 = require("./http-client");
25
- const utils_1 = require("./utils");
26
- /**
27
- * Socket SDK for programmatic access to Socket.dev security analysis APIs.
28
- * Provides methods for package scanning, organization management, and security analysis.
29
- */
30
- class SocketSdk {
31
- #apiToken;
32
- #baseUrl;
33
- #reqOptions;
34
- /**
35
- * Initialize Socket SDK with API token and configuration options.
36
- * Sets up authentication, base URL, and HTTP client options.
37
- */
38
- constructor(apiToken, options) {
39
- const { agent: agentOrObj, baseUrl = 'https://api.socket.dev/v0/', timeout, userAgent, } = { __proto__: null, ...options };
40
- const agentKeys = agentOrObj ? Object.keys(agentOrObj) : [];
41
- const agentAsGotOptions = agentOrObj;
42
- const agent = (agentKeys.length && agentKeys.every(k => constants_1.httpAgentNames.has(k))
43
- ? /* c8 ignore next 3 - Got-style agent options compatibility layer */
44
- agentAsGotOptions.https ||
45
- agentAsGotOptions.http ||
46
- agentAsGotOptions.http2
47
- : agentOrObj);
48
- this.#apiToken = apiToken;
49
- this.#baseUrl = (0, utils_1.normalizeBaseUrl)(baseUrl);
50
- this.#reqOptions = {
51
- ...(agent ? { agent } : {}),
52
- headers: {
53
- Authorization: `Basic ${btoa(`${apiToken}:`)}`,
54
- 'User-Agent': userAgent ?? constants_1.DEFAULT_USER_AGENT,
55
- },
56
- signal: abort_signal_1.default,
57
- ...(timeout ? { timeout } : {}),
58
- };
59
- }
60
- /**
61
- * Create HTTP request for batch package URL processing.
62
- * Internal method for handling PURL batch API calls with retry logic.
63
- */
64
- async #createBatchPurlRequest(componentsObj, queryParams) {
65
- // Adds the first 'abort' listener to abortSignal.
66
- const req = (0, http_client_1.getHttpModule)(this.#baseUrl)
67
- .request(`${this.#baseUrl}purl?${(0, utils_1.queryToSearchParams)(queryParams)}`, {
68
- method: 'POST',
69
- ...this.#reqOptions,
70
- })
71
- .end(JSON.stringify(componentsObj));
72
- const response = await (0, http_client_1.getResponse)(req);
73
- // Throw ResponseError for non-2xx status codes so retry logic works properly.
74
- if (!(0, http_client_1.isResponseOk)(response)) {
75
- throw new http_client_1.ResponseError(response);
76
- }
77
- return response;
78
- }
79
- /**
80
- * Create async generator for streaming batch package URL processing.
81
- * Internal method for handling chunked PURL responses with error handling.
82
- */
83
- async *#createBatchPurlGenerator(componentsObj, queryParams) {
84
- let res;
85
- try {
86
- res = await (0, promises_1.pRetry)(() => this.#createBatchPurlRequest(componentsObj, queryParams), {
87
- retries: 4,
88
- onRetryRethrow: true,
89
- onRetry(_attempt, error) {
90
- /* c8 ignore next 3 - Early return for non-ResponseError types in retry logic, difficult to test without complex network error simulation. */
91
- if (!(error instanceof http_client_1.ResponseError)) {
92
- return;
93
- }
94
- const { statusCode } = error.response;
95
- // Don't retry authentication/authorization errors - they won't succeed.
96
- if (statusCode === 401 || statusCode === 403) {
97
- throw error;
98
- }
99
- },
100
- });
101
- }
102
- catch (e) {
103
- yield await this.#handleApiError(e);
104
- return;
105
- }
106
- // Parse the newline delimited JSON response.
107
- const rli = node_readline_1.default.createInterface({
108
- input: res,
109
- crlfDelay: Infinity,
110
- signal: abort_signal_1.default,
111
- });
112
- const isPublicToken = this.#apiToken === socket_public_api_token_1.default;
113
- for await (const line of rli) {
114
- const trimmed = line.trim();
115
- const artifact = trimmed
116
- ? (0, json_1.jsonParse)(line, { throws: false })
117
- : /* c8 ignore next - Empty line handling in batch streaming response parsing. */ null;
118
- if ((0, objects_1.isObjectObject)(artifact)) {
119
- yield this.#handleApiSuccess(isPublicToken
120
- ? /* c8 ignore start - Public token artifact reshaping branch for policy compliance. */ (0, http_client_1.reshapeArtifactForPublicPolicy)(artifact, false, queryParams?.['actions'])
121
- : /* c8 ignore stop */
122
- artifact);
123
- }
124
- }
125
- }
126
- /**
127
- * Handle API error responses and convert to standardized error result.
128
- * Internal error handling with status code analysis and message formatting.
129
- */
130
- async #handleApiError(error) {
131
- if (!(error instanceof http_client_1.ResponseError)) {
132
- throw new Error('Unexpected Socket API error', {
133
- cause: error,
134
- });
135
- }
136
- const { statusCode } = error.response;
137
- // Throw server errors (5xx) immediately - these are not recoverable client-side.
138
- if (statusCode && statusCode >= 500) {
139
- throw new Error(`Socket API server error (${statusCode})`, {
140
- cause: error,
141
- });
142
- }
143
- // The error payload may give a meaningful hint as to what went wrong.
144
- const bodyStr = await (0, http_client_1.getErrorResponseBody)(error.response);
145
- // Try to parse the body as JSON, fallback to treating as plain text.
146
- let body;
147
- try {
148
- const parsed = JSON.parse(bodyStr);
149
- // Client errors (4xx) should return actionable error messages.
150
- // Extract both message and details from error response for better context.
151
- if (typeof parsed?.error?.message === 'string') {
152
- body = parsed.error.message;
153
- // Include details if present for additional error context.
154
- if (parsed.error.details) {
155
- const detailsStr = typeof parsed.error.details === 'string'
156
- ? parsed.error.details
157
- : JSON.stringify(parsed.error.details);
158
- body = `${body} - Details: ${detailsStr}`;
159
- }
160
- }
161
- }
162
- catch {
163
- body = bodyStr;
164
- }
165
- // Build error message that includes the body content if available.
166
- let errorMessage = error.message ?? unknown_error_1.default;
167
- const trimmedBody = body?.trim();
168
- if (trimmedBody && !errorMessage.includes(trimmedBody)) {
169
- // Replace generic status message with actual error body if present,
170
- // otherwise append the body to the error message.
171
- const statusMessage = error.response?.statusMessage;
172
- if (statusMessage && errorMessage.includes(statusMessage)) {
173
- errorMessage = errorMessage.replace(statusMessage, trimmedBody);
174
- }
175
- else {
176
- /* c8 ignore next 2 - edge case where statusMessage is undefined or not in error message. */
177
- errorMessage = `${errorMessage}: ${trimmedBody}`;
178
- }
179
- }
180
- return {
181
- success: false,
182
- /* c8 ignore next - fallback for missing status code in edge cases. */
183
- status: statusCode ?? 0,
184
- error: errorMessage,
185
- cause: body,
186
- };
187
- }
188
- /**
189
- * Handle successful API responses and convert to standardized success result.
190
- * Internal success handling with consistent response formatting.
191
- */
192
- #handleApiSuccess(data) {
193
- return {
194
- success: true,
195
- // Use generic 200 OK status for all successful API responses.
196
- status: 200,
197
- data: data,
198
- };
199
- }
200
- /**
201
- * Fetch package analysis data for multiple packages in a single batch request.
202
- * Returns all results at once after processing is complete.
203
- *
204
- * @throws {Error} When server returns 5xx status codes
205
- */
206
- async batchPackageFetch(componentsObj, queryParams) {
207
- let res;
208
- try {
209
- res = await this.#createBatchPurlRequest(componentsObj, queryParams);
210
- }
211
- catch (e) {
212
- return await this.#handleApiError(e);
213
- }
214
- // Parse the newline delimited JSON response.
215
- const rli = node_readline_1.default.createInterface({
216
- input: res,
217
- crlfDelay: Infinity,
218
- signal: abort_signal_1.default,
219
- });
220
- const isPublicToken = this.#apiToken === socket_public_api_token_1.default;
221
- const results = [];
222
- for await (const line of rli) {
223
- const trimmed = line.trim();
224
- const artifact = trimmed
225
- ? (0, json_1.jsonParse)(line, { throws: false })
226
- : /* c8 ignore next - Empty line handling in batch parsing. */ null;
227
- if ((0, objects_1.isObjectObject)(artifact)) {
228
- results.push(isPublicToken
229
- ? /* c8 ignore start - Public token artifact reshaping for policy compliance. */
230
- (0, http_client_1.reshapeArtifactForPublicPolicy)(artifact, false, queryParams?.['actions'])
231
- : /* c8 ignore stop */
232
- artifact);
233
- }
234
- }
235
- const compact = (0, url_1.urlSearchParamAsBoolean)((0, objects_1.getOwn)(queryParams, 'compact'));
236
- return this.#handleApiSuccess(compact ? results : results);
237
- }
238
- /**
239
- * Stream package analysis data for multiple packages with chunked processing and concurrency control.
240
- * Returns results as they become available via async generator.
241
- *
242
- * @throws {Error} When server returns 5xx status codes
243
- */
244
- async *batchPackageStream(componentsObj, options) {
245
- const { chunkSize = 100, concurrencyLimit = 10, queryParams, } = {
246
- __proto__: null,
247
- ...options,
248
- };
249
- // The createBatchPurlGenerator method will add 2 'abort' event listeners to
250
- // abortSignal so we multiply the concurrencyLimit by 2.
251
- const neededMaxListeners = concurrencyLimit * 2;
252
- // Increase abortSignal max listeners count to avoid Node's MaxListenersExceededWarning.
253
- const oldAbortSignalMaxListeners = node_events_1.default.getMaxListeners(abort_signal_1.default);
254
- let abortSignalMaxListeners = oldAbortSignalMaxListeners;
255
- /* c8 ignore start - EventTarget max listeners adjustment for high concurrency batch operations, difficult to test reliably. */
256
- if (oldAbortSignalMaxListeners < neededMaxListeners) {
257
- abortSignalMaxListeners = oldAbortSignalMaxListeners + neededMaxListeners;
258
- node_events_1.default.setMaxListeners(abortSignalMaxListeners, abort_signal_1.default);
259
- }
260
- /* c8 ignore stop */
261
- const { components } = componentsObj;
262
- const { length: componentsCount } = components;
263
- const running = [];
264
- let index = 0;
265
- const enqueueGen = () => {
266
- if (index >= componentsCount) {
267
- // No more work to do.
268
- return;
269
- }
270
- const generator = this.#createBatchPurlGenerator({
271
- // Chunk components.
272
- components: components.slice(index, index + chunkSize),
273
- }, queryParams);
274
- continueGen(generator);
275
- index += chunkSize;
276
- };
277
- const continueGen = (generator) => {
278
- const { promise, reject: rejectFn, resolve: resolveFn, } = (0, utils_1.promiseWithResolvers)();
279
- running.push({
280
- generator,
281
- promise,
282
- });
283
- void generator
284
- .next()
285
- .then(iteratorResult => resolveFn({ generator, iteratorResult }), rejectFn);
286
- };
287
- // Start initial batch of generators.
288
- while (running.length < concurrencyLimit && index < componentsCount) {
289
- enqueueGen();
290
- }
291
- while (running.length > 0) {
292
- // eslint-disable-next-line no-await-in-loop
293
- const { generator, iteratorResult } = await Promise.race(running.map(entry => entry.promise));
294
- // Remove generator.
295
- /* c8 ignore next 3 - Concurrent generator cleanup edge case. */
296
- running.splice(running.findIndex(entry => entry.generator === generator), 1);
297
- // Yield the value if one is given, even when done:true.
298
- if (iteratorResult.value) {
299
- yield iteratorResult.value;
300
- }
301
- if (iteratorResult.done) {
302
- // Start a new generator if available.
303
- enqueueGen();
304
- }
305
- else {
306
- // Keep fetching values from this generator.
307
- continueGen(generator);
308
- }
309
- }
310
- // Reset abortSignal max listeners count.
311
- /* c8 ignore start - Reset EventTarget max listeners to original value after batch operations. */
312
- if (abortSignalMaxListeners > oldAbortSignalMaxListeners) {
313
- node_events_1.default.setMaxListeners(oldAbortSignalMaxListeners, abort_signal_1.default);
314
- }
315
- /* c8 ignore stop */
316
- }
317
- /**
318
- * Create a snapshot of project dependencies by uploading manifest files.
319
- * Analyzes dependency files to generate a comprehensive security report.
320
- *
321
- * @throws {Error} When server returns 5xx status codes
322
- */
323
- async createDependenciesSnapshot(filepaths, pathsRelativeTo = '.', queryParams) {
324
- const basePath = (0, utils_1.resolveBasePath)(pathsRelativeTo);
325
- const absFilepaths = (0, utils_1.resolveAbsPaths)(filepaths, basePath);
326
- try {
327
- const data = await (0, http_client_1.getResponseJson)(await (0, file_upload_1.createUploadRequest)(this.#baseUrl, `dependencies/upload?${(0, utils_1.queryToSearchParams)(queryParams)}`, (0, file_upload_1.createRequestBodyForFilepaths)(absFilepaths, basePath), this.#reqOptions));
328
- return this.#handleApiSuccess(data);
329
- }
330
- catch (e) {
331
- return await this.#handleApiError(e);
332
- }
333
- }
334
- /**
335
- * Create a comprehensive security scan for an organization.
336
- * Uploads project files and initiates full security analysis.
337
- *
338
- * @throws {Error} When server returns 5xx status codes
339
- */
340
- async createOrgFullScan(orgSlug, filepaths, pathsRelativeTo = '.', queryParams) {
341
- const basePath = (0, utils_1.resolveBasePath)(pathsRelativeTo);
342
- const absFilepaths = (0, utils_1.resolveAbsPaths)(filepaths, basePath);
343
- try {
344
- const data = await (0, http_client_1.getResponseJson)(await (0, file_upload_1.createUploadRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/full-scans?${(0, utils_1.queryToSearchParams)(queryParams)}`, (0, file_upload_1.createRequestBodyForFilepaths)(absFilepaths, basePath), this.#reqOptions));
345
- return this.#handleApiSuccess(data);
346
- }
347
- catch (e) {
348
- return await this.#handleApiError(e);
349
- }
350
- }
351
- /**
352
- * Create a new repository in an organization.
353
- * Registers a repository for monitoring and security scanning.
354
- *
355
- * @throws {Error} When server returns 5xx status codes
356
- */
357
- async createOrgRepo(orgSlug, queryParams) {
358
- try {
359
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/repos`, queryParams, this.#reqOptions));
360
- return this.#handleApiSuccess(data);
361
- }
362
- catch (e) {
363
- return await this.#handleApiError(e);
364
- }
365
- }
366
- /**
367
- * Create a security scan by uploading project files.
368
- * Analyzes uploaded files for security vulnerabilities and policy violations.
369
- *
370
- * @throws {Error} When server returns 5xx status codes
371
- */
372
- async createScanFromFilepaths(filepaths, pathsRelativeTo = '.', issueRules) {
373
- const basePath = (0, utils_1.resolveBasePath)(pathsRelativeTo);
374
- const absFilepaths = (0, utils_1.resolveAbsPaths)(filepaths, basePath);
375
- try {
376
- const data = await (0, http_client_1.getResponseJson)(await (0, file_upload_1.createUploadRequest)(this.#baseUrl, 'report/upload', [
377
- ...(0, file_upload_1.createRequestBodyForFilepaths)(absFilepaths, basePath),
378
- /* c8 ignore next 3 - Optional issueRules parameter edge case. */
379
- ...(issueRules
380
- ? (0, file_upload_1.createRequestBodyForJson)(issueRules, 'issueRules')
381
- : []),
382
- ], {
383
- ...this.#reqOptions,
384
- method: 'PUT',
385
- })
386
- /* c8 ignore next 3 - Success path return statement requires complex file upload mocking with authentication. */
387
- );
388
- return this.#handleApiSuccess(data);
389
- }
390
- catch (e) {
391
- return await this.#handleApiError(e);
392
- }
393
- }
394
- /**
395
- * Delete a full scan from an organization.
396
- * Permanently removes scan data and results.
397
- *
398
- * @throws {Error} When server returns 5xx status codes
399
- */
400
- async deleteOrgFullScan(orgSlug, fullScanId) {
401
- try {
402
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createDeleteRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/full-scans/${encodeURIComponent(fullScanId)}`, this.#reqOptions));
403
- return this.#handleApiSuccess(data);
404
- }
405
- catch (e) {
406
- return await this.#handleApiError(e);
407
- }
408
- }
409
- /**
410
- * Delete a repository from an organization.
411
- * Removes repository monitoring and associated scan data.
412
- *
413
- * @throws {Error} When server returns 5xx status codes
414
- */
415
- async deleteOrgRepo(orgSlug, repoSlug) {
416
- try {
417
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createDeleteRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/repos/${encodeURIComponent(repoSlug)}`, this.#reqOptions));
418
- return this.#handleApiSuccess(data);
419
- }
420
- catch (e) {
421
- return await this.#handleApiError(e);
422
- }
423
- }
424
- /**
425
- * Retrieve audit log events for an organization.
426
- * Returns chronological log of security and administrative actions.
427
- *
428
- * @throws {Error} When server returns 5xx status codes
429
- */
430
- async getAuditLogEvents(orgSlug, queryParams) {
431
- try {
432
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/audit-log?${(0, utils_1.queryToSearchParams)(queryParams)}`, this.#reqOptions));
433
- return this.#handleApiSuccess(data);
434
- }
435
- catch (e) {
436
- return await this.#handleApiError(e);
437
- }
438
- }
439
- /**
440
- * Retrieve the enabled entitlements for an organization.
441
- *
442
- * This method fetches the organization's entitlements and filters for only
443
- * the enabled ones, returning their keys. Entitlements represent Socket
444
- * Products that the organization has access to use.
445
- */
446
- async getEnabledEntitlements(orgSlug) {
447
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/entitlements`, this.#reqOptions));
448
- // Extract enabled products from the response.
449
- const items = data?.items || [];
450
- return items
451
- .filter((item) => item && item.enabled === true && item.key)
452
- .map((item) => item.key);
453
- }
454
- /**
455
- * Retrieve all entitlements for an organization.
456
- *
457
- * This method fetches all entitlements (both enabled and disabled) for
458
- * an organization, returning the complete list with their status.
459
- */
460
- async getEntitlements(orgSlug) {
461
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/entitlements`, this.#reqOptions));
462
- return data?.items || [];
463
- }
464
- /**
465
- * Get security issues for a specific npm package and version.
466
- * Returns detailed vulnerability and security alert information.
467
- *
468
- * @throws {Error} When server returns 5xx status codes
469
- */
470
- async getIssuesByNpmPackage(pkgName, version) {
471
- try {
472
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `npm/${encodeURIComponent(pkgName)}/${encodeURIComponent(version)}/issues`, this.#reqOptions));
473
- return this.#handleApiSuccess(data);
474
- }
475
- catch (e) {
476
- return await this.#handleApiError(e);
477
- }
478
- }
479
- /**
480
- * Get analytics data for organization usage patterns and security metrics.
481
- * Returns statistical analysis for specified time period.
482
- *
483
- * @throws {Error} When server returns 5xx status codes
484
- */
485
- async getOrgAnalytics(time) {
486
- try {
487
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `analytics/org/${encodeURIComponent(time)}`, this.#reqOptions));
488
- return this.#handleApiSuccess(data);
489
- }
490
- catch (e) {
491
- return await this.#handleApiError(e);
492
- }
493
- }
494
- /**
495
- * List all organizations accessible to the current user.
496
- * Returns organization details and access permissions.
497
- *
498
- * @throws {Error} When server returns 5xx status codes
499
- */
500
- async getOrganizations() {
501
- try {
502
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, 'organizations', this.#reqOptions));
503
- return this.#handleApiSuccess(data);
504
- }
505
- catch (e) {
506
- return await this.#handleApiError(e);
507
- }
508
- }
509
- /**
510
- * Stream a full scan's results to file or stdout.
511
- * Provides efficient streaming for large scan datasets.
512
- *
513
- * @throws {Error} When server returns 5xx status codes
514
- */
515
- async streamOrgFullScan(orgSlug, fullScanId, output) {
516
- try {
517
- const req = (0, http_client_1.getHttpModule)(this.#baseUrl)
518
- .request(`${this.#baseUrl}orgs/${encodeURIComponent(orgSlug)}/full-scans/${encodeURIComponent(fullScanId)}`, {
519
- method: 'GET',
520
- ...this.#reqOptions,
521
- })
522
- .end();
523
- const res = await (0, http_client_1.getResponse)(req);
524
- // Check for HTTP error status codes.
525
- if (!(0, http_client_1.isResponseOk)(res)) {
526
- throw new http_client_1.ResponseError(res);
527
- }
528
- if (typeof output === 'string') {
529
- // Stream to file
530
- res.pipe((0, node_fs_1.createWriteStream)(output));
531
- }
532
- else if (output === true) {
533
- // Stream to stdout
534
- res.pipe(process.stdout);
535
- }
536
- // If output is false or undefined, just return the response without streaming
537
- return this.#handleApiSuccess(res);
538
- }
539
- catch (e) {
540
- return await this.#handleApiError(e);
541
- }
542
- }
543
- /**
544
- * Stream patches for artifacts in a scan report.
545
- *
546
- * This method streams all available patches for artifacts in a scan.
547
- * Free tier users will only receive free patches.
548
- *
549
- * Note: This method returns a ReadableStream for processing large datasets.
550
- */
551
- async streamPatchesFromScan(orgSlug, scanId) {
552
- const response = await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/patches/scan/${encodeURIComponent(scanId)}`, this.#reqOptions);
553
- // Check for HTTP error status codes.
554
- if (!(0, http_client_1.isResponseOk)(response)) {
555
- throw new http_client_1.ResponseError(response, 'GET Request failed');
556
- }
557
- // The response itself is the readable stream for NDJSON data
558
- // Convert the Node.js readable stream to a Web ReadableStream
559
- return new ReadableStream({
560
- start(controller) {
561
- response.on('data', (chunk) => {
562
- // Parse NDJSON chunks line by line
563
- const lines = chunk
564
- .toString()
565
- .split('\n')
566
- .filter(line => line.trim());
567
- for (const line of lines) {
568
- try {
569
- const data = JSON.parse(line);
570
- controller.enqueue(data);
571
- }
572
- catch (e) {
573
- // Skip invalid JSON lines
574
- continue;
575
- }
576
- }
577
- });
578
- response.on('end', () => {
579
- controller.close();
580
- });
581
- response.on('error', error => {
582
- /* c8 ignore next - Streaming error handler, difficult to test reliably. */
583
- controller.error(error);
584
- });
585
- },
586
- });
587
- }
588
- /**
589
- * Get complete full scan results in memory.
590
- * Returns entire scan data as JSON for programmatic processing.
591
- *
592
- * @throws {Error} When server returns 5xx status codes
593
- */
594
- async getOrgFullScanBuffered(orgSlug, fullScanId) {
595
- try {
596
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/full-scans/${encodeURIComponent(fullScanId)}`, this.#reqOptions));
597
- return this.#handleApiSuccess(data);
598
- }
599
- catch (e) {
600
- return await this.#handleApiError(e);
601
- }
602
- }
603
- /**
604
- * List all full scans for an organization.
605
- * Returns paginated list of scan metadata and status.
606
- *
607
- * @throws {Error} When server returns 5xx status codes
608
- */
609
- async getOrgFullScanList(orgSlug, queryParams) {
610
- try {
611
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/full-scans?${(0, utils_1.queryToSearchParams)(queryParams)}`, this.#reqOptions));
612
- return this.#handleApiSuccess(data);
613
- }
614
- catch (e) {
615
- return await this.#handleApiError(e);
616
- }
617
- }
618
- /**
619
- * Get metadata for a specific full scan.
620
- * Returns scan configuration, status, and summary information.
621
- *
622
- * @throws {Error} When server returns 5xx status codes
623
- */
624
- async getOrgFullScanMetadata(orgSlug, fullScanId) {
625
- try {
626
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/full-scans/${encodeURIComponent(fullScanId)}/metadata`, this.#reqOptions));
627
- return this.#handleApiSuccess(data);
628
- }
629
- catch (e) {
630
- return await this.#handleApiError(e);
631
- }
632
- }
633
- /**
634
- * Get organization's license policy configuration.
635
- * Returns allowed, restricted, and monitored license types.
636
- *
637
- * @throws {Error} When server returns 5xx status codes
638
- */
639
- async getOrgLicensePolicy(orgSlug) {
640
- try {
641
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/settings/license-policy`, this.#reqOptions));
642
- return this.#handleApiSuccess(data);
643
- }
644
- catch (e) {
645
- return await this.#handleApiError(e);
646
- }
647
- }
648
- /**
649
- * Get details for a specific organization repository.
650
- * Returns repository configuration, monitoring status, and metadata.
651
- *
652
- * @throws {Error} When server returns 5xx status codes
653
- */
654
- async getOrgRepo(orgSlug, repoSlug) {
655
- const orgSlugParam = encodeURIComponent(orgSlug);
656
- const repoSlugParam = encodeURIComponent(repoSlug);
657
- try {
658
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${orgSlugParam}/repos/${repoSlugParam}`, this.#reqOptions));
659
- return this.#handleApiSuccess(data);
660
- }
661
- catch (e) {
662
- return await this.#handleApiError(e);
663
- }
664
- }
665
- /**
666
- * List all repositories in an organization.
667
- * Returns paginated list of repository metadata and status.
668
- *
669
- * @throws {Error} When server returns 5xx status codes
670
- */
671
- async getOrgRepoList(orgSlug, queryParams) {
672
- try {
673
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/repos?${(0, utils_1.queryToSearchParams)(queryParams)}`, this.#reqOptions));
674
- return this.#handleApiSuccess(data);
675
- }
676
- catch (e) {
677
- return await this.#handleApiError(e);
678
- }
679
- }
680
- /**
681
- * Get organization's security policy configuration.
682
- * Returns alert rules, severity thresholds, and enforcement settings.
683
- *
684
- * @throws {Error} When server returns 5xx status codes
685
- */
686
- async getOrgSecurityPolicy(orgSlug) {
687
- try {
688
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/settings/security-policy`, this.#reqOptions));
689
- return this.#handleApiSuccess(data);
690
- }
691
- catch (e) {
692
- return await this.#handleApiError(e);
693
- }
694
- }
695
- /**
696
- * Get current API quota usage and limits.
697
- * Returns remaining requests, rate limits, and quota reset times.
698
- *
699
- * @throws {Error} When server returns 5xx status codes
700
- */
701
- async getQuota() {
702
- try {
703
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, 'quota', this.#reqOptions));
704
- return this.#handleApiSuccess(data);
705
- }
706
- catch (e) {
707
- return await this.#handleApiError(e);
708
- }
709
- }
710
- /**
711
- * Get analytics data for a specific repository.
712
- * Returns security metrics, dependency trends, and vulnerability statistics.
713
- *
714
- * @throws {Error} When server returns 5xx status codes
715
- */
716
- async getRepoAnalytics(repo, time) {
717
- try {
718
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `analytics/repo/${encodeURIComponent(repo)}/${encodeURIComponent(time)}`, this.#reqOptions));
719
- return this.#handleApiSuccess(data);
720
- }
721
- catch (e) {
722
- return await this.#handleApiError(e);
723
- }
724
- }
725
- /**
726
- * Get detailed results for a specific scan.
727
- * Returns complete scan analysis including vulnerabilities and alerts.
728
- *
729
- * @throws {Error} When server returns 5xx status codes
730
- */
731
- async getScan(id) {
732
- try {
733
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `report/view/${encodeURIComponent(id)}`, this.#reqOptions));
734
- return this.#handleApiSuccess(data);
735
- }
736
- catch (e) {
737
- return await this.#handleApiError(e);
738
- }
739
- }
740
- /**
741
- * List all scans accessible to the current user.
742
- * Returns paginated list of scan metadata and status.
743
- *
744
- * @throws {Error} When server returns 5xx status codes
745
- */
746
- async getScanList() {
747
- try {
748
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, 'report/list', this.#reqOptions), 'GET');
749
- return this.#handleApiSuccess(data);
750
- }
751
- catch (e) {
752
- return await this.#handleApiError(e);
753
- }
754
- }
755
- /**
756
- * Get list of file types and formats supported for scanning.
757
- * Returns supported manifest files, lockfiles, and configuration formats.
758
- *
759
- * @throws {Error} When server returns 5xx status codes
760
- */
761
- async getSupportedScanFiles() {
762
- try {
763
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, 'report/supported', this.#reqOptions));
764
- return this.#handleApiSuccess(data);
765
- }
766
- catch (e) {
767
- return await this.#handleApiError(e);
768
- }
769
- }
770
- /**
771
- * Get security score for a specific npm package and version.
772
- * Returns numerical security rating and scoring breakdown.
773
- *
774
- * @throws {Error} When server returns 5xx status codes
775
- */
776
- async getScoreByNpmPackage(pkgName, version) {
777
- try {
778
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `npm/${encodeURIComponent(pkgName)}/${encodeURIComponent(version)}/score`, this.#reqOptions));
779
- return this.#handleApiSuccess(data);
780
- }
781
- catch (e) {
782
- return await this.#handleApiError(e);
783
- }
784
- }
785
- /**
786
- * Update user or organization settings.
787
- * Configures preferences, notifications, and security policies.
788
- *
789
- * @throws {Error} When server returns 5xx status codes
790
- */
791
- async postSettings(selectors) {
792
- try {
793
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, 'settings', { json: selectors }, this.#reqOptions));
794
- return this.#handleApiSuccess(data);
795
- }
796
- catch (e) {
797
- return await this.#handleApiError(e);
798
- }
799
- }
800
- /**
801
- * Search for dependencies across monitored projects.
802
- * Returns matching packages with security information and usage patterns.
803
- *
804
- * @throws {Error} When server returns 5xx status codes
805
- */
806
- async searchDependencies(queryParams) {
807
- try {
808
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, 'dependencies/search', queryParams, this.#reqOptions));
809
- return this.#handleApiSuccess(data);
810
- }
811
- catch (e) {
812
- return await this.#handleApiError(e);
813
- }
814
- }
815
- /**
816
- * Update configuration for an organization repository.
817
- * Modifies monitoring settings, branch configuration, and scan preferences.
818
- *
819
- * @throws {Error} When server returns 5xx status codes
820
- */
821
- async updateOrgRepo(orgSlug, repoSlug, queryParams) {
822
- try {
823
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/repos/${encodeURIComponent(repoSlug)}`, queryParams, this.#reqOptions));
824
- return this.#handleApiSuccess(data);
825
- }
826
- catch (e) {
827
- return await this.#handleApiError(e);
828
- }
829
- }
830
- /**
831
- * Upload manifest files for dependency analysis.
832
- * Processes package files to create dependency snapshots and security analysis.
833
- *
834
- * @throws {Error} When server returns 5xx status codes
835
- */
836
- async uploadManifestFiles(orgSlug, filepaths, pathsRelativeTo = '.') {
837
- const basePath = (0, utils_1.resolveBasePath)(pathsRelativeTo);
838
- const absFilepaths = (0, utils_1.resolveAbsPaths)(filepaths, basePath);
839
- try {
840
- const data = await (0, http_client_1.getResponseJson)(await (0, file_upload_1.createUploadRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/upload-manifest-files`, (0, file_upload_1.createRequestBodyForFilepaths)(absFilepaths, basePath), this.#reqOptions));
841
- return this.#handleApiSuccess(data);
842
- }
843
- catch (e) {
844
- /* c8 ignore start - Error handling in uploadManifestFiles method for edge cases. */
845
- return (await this.#handleApiError(e));
846
- /* c8 ignore stop */
847
- } /* c8 ignore next - Closing brace of error handling block. */
848
- }
849
- /**
850
- * View detailed information about a specific patch by its UUID.
851
- *
852
- * This method retrieves comprehensive patch details including files,
853
- * vulnerabilities, description, license, and tier information.
854
- */
855
- async viewPatch(orgSlug, uuid) {
856
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/patches/view/${encodeURIComponent(uuid)}`, this.#reqOptions));
857
- return data;
858
- }
859
- /**
860
- * Delete a scan report permanently.
861
- * Removes scan data and analysis results from the system.
862
- *
863
- * @throws {Error} When server returns 5xx status codes
864
- */
865
- async deleteReport(reportId) {
866
- try {
867
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createDeleteRequest)(this.#baseUrl, `report/delete/${encodeURIComponent(reportId)}`, this.#reqOptions));
868
- return this.#handleApiSuccess(data);
869
- }
870
- catch (e) {
871
- return await this.#handleApiError(e);
872
- }
873
- }
874
- /**
875
- * Export scan results in CycloneDX SBOM format.
876
- * Returns Software Bill of Materials compliant with CycloneDX standard.
877
- *
878
- * @throws {Error} When server returns 5xx status codes
879
- */
880
- async exportCDX(orgSlug, fullScanId) {
881
- try {
882
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/full-scans/${encodeURIComponent(fullScanId)}/sbom/export/cdx`, this.#reqOptions));
883
- return this.#handleApiSuccess(data);
884
- }
885
- catch (e) {
886
- return await this.#handleApiError(e);
887
- }
888
- }
889
- /**
890
- * Export scan results in SPDX SBOM format.
891
- * Returns Software Bill of Materials compliant with SPDX standard.
892
- *
893
- * @throws {Error} When server returns 5xx status codes
894
- */
895
- async exportSPDX(orgSlug, fullScanId) {
896
- try {
897
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/full-scans/${encodeURIComponent(fullScanId)}/sbom/export/spdx`, this.#reqOptions));
898
- return this.#handleApiSuccess(data);
899
- }
900
- catch (e) {
901
- return await this.#handleApiError(e);
902
- }
903
- }
904
- /**
905
- * Get list of API tokens for an organization.
906
- * Returns organization API tokens with metadata and permissions.
907
- *
908
- * @throws {Error} When server returns 5xx status codes
909
- */
910
- async getAPITokens(orgSlug) {
911
- try {
912
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/tokens`, this.#reqOptions));
913
- return this.#handleApiSuccess(data);
914
- }
915
- catch (e) {
916
- return await this.#handleApiError(e);
917
- }
918
- }
919
- /**
920
- * Create a new API token for an organization.
921
- * Generates API token with specified scopes and metadata.
922
- *
923
- * @throws {Error} When server returns 5xx status codes
924
- */
925
- async postAPIToken(orgSlug, tokenData) {
926
- try {
927
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/tokens`, tokenData, this.#reqOptions));
928
- return this.#handleApiSuccess(data);
929
- }
930
- catch (e) {
931
- return await this.#handleApiError(e);
932
- }
933
- }
934
- /**
935
- * Update an existing API token for an organization.
936
- * Modifies token metadata, scopes, or other properties.
937
- *
938
- * @throws {Error} When server returns 5xx status codes
939
- */
940
- async postAPITokenUpdate(orgSlug, tokenId, updateData) {
941
- try {
942
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/tokens/${encodeURIComponent(tokenId)}/update`, updateData, this.#reqOptions));
943
- return this.#handleApiSuccess(data);
944
- }
945
- catch (e) {
946
- return await this.#handleApiError(e);
947
- }
948
- }
949
- /**
950
- * Rotate an API token for an organization.
951
- * Generates new token value while preserving token metadata.
952
- *
953
- * @throws {Error} When server returns 5xx status codes
954
- */
955
- async postAPITokensRotate(orgSlug, tokenId) {
956
- try {
957
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/tokens/${encodeURIComponent(tokenId)}/rotate`, {}, this.#reqOptions));
958
- return this.#handleApiSuccess(data);
959
- }
960
- catch (e) {
961
- return await this.#handleApiError(e);
962
- }
963
- }
964
- /**
965
- * Revoke an API token for an organization.
966
- * Permanently disables the token and removes access.
967
- *
968
- * @throws {Error} When server returns 5xx status codes
969
- */
970
- async postAPITokensRevoke(orgSlug, tokenId) {
971
- try {
972
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/tokens/${encodeURIComponent(tokenId)}/revoke`, {}, this.#reqOptions));
973
- return this.#handleApiSuccess(data);
974
- }
975
- catch (e) {
976
- return await this.#handleApiError(e);
977
- }
978
- }
979
- /**
980
- * Update organization's security policy configuration.
981
- * Modifies alert rules, severity thresholds, and enforcement settings.
982
- *
983
- * @throws {Error} When server returns 5xx status codes
984
- */
985
- async updateOrgSecurityPolicy(orgSlug, policyData) {
986
- try {
987
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/settings/security-policy`, policyData, this.#reqOptions));
988
- return this.#handleApiSuccess(data);
989
- }
990
- catch (e) {
991
- return await this.#handleApiError(e);
992
- }
993
- }
994
- /**
995
- * Update organization's license policy configuration.
996
- * Modifies allowed, restricted, and monitored license types.
997
- *
998
- * @throws {Error} When server returns 5xx status codes
999
- */
1000
- async updateOrgLicensePolicy(orgSlug, policyData, queryParams) {
1001
- try {
1002
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/settings/license-policy?${(0, utils_1.queryToSearchParams)(queryParams)}`, policyData, this.#reqOptions));
1003
- return this.#handleApiSuccess(data);
1004
- }
1005
- catch (e) {
1006
- return await this.#handleApiError(e);
1007
- }
1008
- }
1009
- /**
1010
- * Get organization triage settings and status.
1011
- * Returns alert triage configuration and current state.
1012
- *
1013
- * @throws {Error} When server returns 5xx status codes
1014
- */
1015
- async getOrgTriage(orgSlug) {
1016
- try {
1017
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/triage`, this.#reqOptions));
1018
- return this.#handleApiSuccess(data);
1019
- }
1020
- catch (e) {
1021
- return await this.#handleApiError(e);
1022
- }
1023
- }
1024
- /**
1025
- * Update alert triage status for an organization.
1026
- * Modifies alert resolution status and triage decisions.
1027
- *
1028
- * @throws {Error} When server returns 5xx status codes
1029
- */
1030
- async updateOrgAlertTriage(orgSlug, alertId, triageData) {
1031
- try {
1032
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('PUT', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/triage/${encodeURIComponent(alertId)}`, triageData, this.#reqOptions));
1033
- return this.#handleApiSuccess(data);
1034
- }
1035
- catch (e) {
1036
- return await this.#handleApiError(e);
1037
- }
1038
- }
1039
- /**
1040
- * Get list of repository labels for an organization.
1041
- * Returns all labels configured for repository management.
1042
- *
1043
- * @throws {Error} When server returns 5xx status codes
1044
- */
1045
- async getOrgRepoLabelList(orgSlug, repoSlug) {
1046
- try {
1047
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/repos/${encodeURIComponent(repoSlug)}/labels`, this.#reqOptions));
1048
- return this.#handleApiSuccess(data);
1049
- }
1050
- catch (e) {
1051
- return await this.#handleApiError(e);
1052
- }
1053
- }
1054
- /**
1055
- * Create a new repository label for an organization.
1056
- * Adds label for repository categorization and management.
1057
- *
1058
- * @throws {Error} When server returns 5xx status codes
1059
- */
1060
- async createOrgRepoLabel(orgSlug, repoSlug, labelData) {
1061
- try {
1062
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/repos/${encodeURIComponent(repoSlug)}/labels`, labelData, this.#reqOptions));
1063
- return this.#handleApiSuccess(data);
1064
- }
1065
- catch (e) {
1066
- return await this.#handleApiError(e);
1067
- }
1068
- }
1069
- /**
1070
- * Get details for a specific repository label.
1071
- * Returns label configuration and metadata.
1072
- *
1073
- * @throws {Error} When server returns 5xx status codes
1074
- */
1075
- async getOrgRepoLabel(orgSlug, repoSlug, labelSlug) {
1076
- try {
1077
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/repos/${encodeURIComponent(repoSlug)}/labels/${encodeURIComponent(labelSlug)}`, this.#reqOptions));
1078
- return this.#handleApiSuccess(data);
1079
- }
1080
- catch (e) {
1081
- return await this.#handleApiError(e);
1082
- }
1083
- }
1084
- /**
1085
- * Update a repository label for an organization.
1086
- * Modifies label properties and configuration.
1087
- *
1088
- * @throws {Error} When server returns 5xx status codes
1089
- */
1090
- async updateOrgRepoLabel(orgSlug, repoSlug, labelSlug, labelData) {
1091
- try {
1092
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('PUT', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/repos/${encodeURIComponent(repoSlug)}/labels/${encodeURIComponent(labelSlug)}`, labelData, this.#reqOptions));
1093
- return this.#handleApiSuccess(data);
1094
- }
1095
- catch (e) {
1096
- return await this.#handleApiError(e);
1097
- }
1098
- }
1099
- /**
1100
- * Delete a repository label from an organization.
1101
- * Removes label and associated configuration.
1102
- *
1103
- * @throws {Error} When server returns 5xx status codes
1104
- */
1105
- async deleteOrgRepoLabel(orgSlug, repoSlug, labelSlug) {
1106
- try {
1107
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createDeleteRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/repos/${encodeURIComponent(repoSlug)}/labels/${encodeURIComponent(labelSlug)}`, this.#reqOptions));
1108
- return this.#handleApiSuccess(data);
1109
- }
1110
- catch (e) {
1111
- return await this.#handleApiError(e);
1112
- }
1113
- }
1114
- /**
1115
- * Get details for a specific diff scan.
1116
- * Returns comparison between two full scans with artifact changes.
1117
- *
1118
- * @throws {Error} When server returns 5xx status codes
1119
- */
1120
- async getDiffScanById(orgSlug, diffScanId) {
1121
- try {
1122
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/diff-scans/${encodeURIComponent(diffScanId)}`, this.#reqOptions));
1123
- return this.#handleApiSuccess(data);
1124
- }
1125
- catch (e) {
1126
- return await this.#handleApiError(e);
1127
- }
1128
- }
1129
- /**
1130
- * Create a diff scan from two full scan IDs.
1131
- * Compares two existing full scans to identify changes.
1132
- *
1133
- * @throws {Error} When server returns 5xx status codes
1134
- */
1135
- async createOrgDiffScanFromIds(orgSlug, queryParams) {
1136
- try {
1137
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createRequestWithJson)('POST', this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/diff-scans?${(0, utils_1.queryToSearchParams)(queryParams)}`, {}, this.#reqOptions));
1138
- return this.#handleApiSuccess(data);
1139
- }
1140
- catch (e) {
1141
- return await this.#handleApiError(e);
1142
- }
1143
- }
1144
- /**
1145
- * List all diff scans for an organization.
1146
- * Returns paginated list of diff scan metadata and status.
1147
- *
1148
- * @throws {Error} When server returns 5xx status codes
1149
- */
1150
- async listOrgDiffScans(orgSlug) {
1151
- try {
1152
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/diff-scans`, this.#reqOptions));
1153
- return this.#handleApiSuccess(data);
1154
- }
1155
- catch (e) {
1156
- return await this.#handleApiError(e);
1157
- }
1158
- }
1159
- /**
1160
- * Delete a diff scan from an organization.
1161
- * Permanently removes diff scan data and results.
1162
- *
1163
- * @throws {Error} When server returns 5xx status codes
1164
- */
1165
- async deleteOrgDiffScan(orgSlug, diffScanId) {
1166
- try {
1167
- const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createDeleteRequest)(this.#baseUrl, `orgs/${encodeURIComponent(orgSlug)}/diff-scans/${encodeURIComponent(diffScanId)}`, this.#reqOptions));
1168
- return this.#handleApiSuccess(data);
1169
- }
1170
- catch (e) {
1171
- return await this.#handleApiError(e);
1172
- }
1173
- }
1174
- /**
1175
- * Handle query API response data based on requested response type.
1176
- * Internal method for processing different response formats (json, text, response).
1177
- */
1178
- async #handleQueryResponseData(response, responseType) {
1179
- if (responseType === 'response') {
1180
- return response;
1181
- }
1182
- if (responseType === 'text') {
1183
- return (await this.#getResponseText(response));
1184
- }
1185
- if (responseType === 'json') {
1186
- return (await (0, http_client_1.getResponseJson)(response));
1187
- }
1188
- return response;
1189
- }
1190
- /**
1191
- * Extract text content from HTTP response stream.
1192
- * Internal method with size limits to prevent memory exhaustion.
1193
- */
1194
- async #getResponseText(response) {
1195
- const chunks = [];
1196
- let size = 0;
1197
- // 50MB limit to prevent out-of-memory errors from large responses.
1198
- const MAX = 50 * 1024 * 1024;
1199
- for await (const chunk of response) {
1200
- size += chunk.length;
1201
- /* c8 ignore next 3 - MAX size limit protection for edge cases */
1202
- if (size > MAX) {
1203
- throw new Error('Response body too large');
1204
- }
1205
- chunks.push(chunk);
1206
- }
1207
- return Buffer.concat(chunks).toString('utf8');
1208
- }
1209
- /**
1210
- * Create standardized error result from query operation exceptions.
1211
- * Internal error handling for non-throwing query API methods.
1212
- */
1213
- #createQueryErrorResult(e) {
1214
- if (e instanceof SyntaxError) {
1215
- // Try to get response text from enhanced error, fall back to regex pattern for compatibility.
1216
- const enhancedError = e;
1217
- let responseText = enhancedError.originalResponse || '';
1218
- /* c8 ignore next 5 - Empty response text fallback check for JSON parsing errors without originalResponse. */
1219
- if (!responseText) {
1220
- const match = e.message.match(/Invalid JSON response:\n([\s\S]*?)\n→/);
1221
- responseText = match?.[1] || '';
1222
- }
1223
- const preview = responseText.slice(0, 100) || '';
1224
- return {
1225
- ok: false,
1226
- message: 'Server returned invalid JSON',
1227
- cause: `Please report this. JSON.parse threw an error over the following response: \`${preview.trim()}${responseText.length > 100 ? '...' : ''}\``,
1228
- };
1229
- }
1230
- /* c8 ignore start - Defensive error stringification fallback branches for edge cases. */
1231
- const errStr = e ? String(e).trim() : '';
1232
- return {
1233
- ok: false,
1234
- message: 'API request failed',
1235
- cause: errStr || unknown_error_1.default,
1236
- };
1237
- /* c8 ignore stop */
1238
- }
1239
- /**
1240
- * Execute a raw GET request to any API endpoint with configurable response type.
1241
- */
1242
- async getApi(urlPath, options) {
1243
- const { responseType = 'response', throws = true } = {
1244
- __proto__: null,
1245
- ...options,
1246
- };
1247
- try {
1248
- const response = await (0, http_client_1.createGetRequest)(this.#baseUrl, urlPath, this.#reqOptions);
1249
- // Check for HTTP error status codes first.
1250
- if (!(0, http_client_1.isResponseOk)(response)) {
1251
- if (throws) {
1252
- throw new http_client_1.ResponseError(response);
1253
- }
1254
- const errorResult = await this.#handleApiError(new http_client_1.ResponseError(response));
1255
- return {
1256
- ok: false,
1257
- code: errorResult.status,
1258
- message: 'Socket API error',
1259
- cause: errorResult.cause || errorResult.error,
1260
- data: { code: errorResult.status },
1261
- };
1262
- }
1263
- const data = await this.#handleQueryResponseData(response, responseType);
1264
- if (throws) {
1265
- return data;
1266
- }
1267
- return {
1268
- ok: true,
1269
- data,
1270
- };
1271
- }
1272
- catch (e) {
1273
- if (throws) {
1274
- throw e;
1275
- }
1276
- if (e instanceof http_client_1.ResponseError) {
1277
- /* c8 ignore start - ResponseError handling in sendApi non-throwing mode */
1278
- // Re-use existing error handling logic from the SDK
1279
- const errorResult = await this.#handleApiError(e);
1280
- return {
1281
- ok: false,
1282
- code: errorResult.status,
1283
- message: 'Socket API error',
1284
- cause: errorResult.cause || errorResult.error,
1285
- data: { code: errorResult.status },
1286
- };
1287
- /* c8 ignore stop */
1288
- } /* c8 ignore next - Closing brace of error result handling. */
1289
- /* c8 ignore next - Fallback error handling for non-ResponseError cases in getApi. */
1290
- return this.#createQueryErrorResult(e);
1291
- }
1292
- }
1293
- /**
1294
- * Send POST or PUT request with JSON body and return parsed JSON response.
1295
- */
1296
- async sendApi(urlPath, options) {
1297
- const { body,
1298
- // Default to POST method for JSON API requests.
1299
- method = 'POST', throws = true, } = { __proto__: null, ...options };
1300
- try {
1301
- // Route to appropriate HTTP method handler (POST or PUT).
1302
- const response = await (0, http_client_1.createRequestWithJson)(method, this.#baseUrl, urlPath, body, this.#reqOptions);
1303
- return {
1304
- ok: true,
1305
- data: (await (0, http_client_1.getResponseJson)(response)),
1306
- };
1307
- }
1308
- catch (e) {
1309
- if (throws) {
1310
- throw e;
1311
- }
1312
- if (e instanceof http_client_1.ResponseError) {
1313
- // Re-use existing error handling logic from the SDK
1314
- const errorResult = await this.#handleApiError(e);
1315
- return {
1316
- ok: false,
1317
- code: errorResult.status,
1318
- message: 'Socket API error',
1319
- cause: errorResult.cause || errorResult.error,
1320
- data: { code: errorResult.status },
1321
- };
1322
- }
1323
- /* c8 ignore start - Defensive error stringification fallback branches for sendApi edge cases. */
1324
- const errStr = e ? String(e).trim() : '';
1325
- return {
1326
- ok: false,
1327
- message: 'API request failed',
1328
- cause: errStr || unknown_error_1.default,
1329
- };
1330
- /* c8 ignore stop */
1331
- }
1332
- }
1333
- }
1334
- exports.SocketSdk = SocketSdk;
1335
- // Optional live heap trace.
1336
- /* c8 ignore start - optional debug logging for heap monitoring */
1337
- if ((0, debug_1.isDebug)('heap')) {
1338
- const used = process.memoryUsage();
1339
- (0, debug_1.debugLog)('heap', `heap used: ${Math.round(used.heapUsed / 1024 / 1024)}MB`);
1340
- }
1341
- /* c8 ignore stop - end debug logging */
1342
- //# sourceMappingURL=socket-sdk-class.js.map