@socketsecurity/sdk 1.9.2 → 1.10.0
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.
- package/CHANGELOG.md +24 -0
- package/README.md +26 -1
- package/dist/constants.js +0 -3
- package/dist/file-upload.js +2 -2
- package/dist/http-client.d.ts +36 -1
- package/dist/http-client.js +86 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +13 -13
- package/dist/promise-queue.d.ts +35 -0
- package/dist/promise-queue.js +91 -0
- package/dist/quota-utils.js +5 -2
- package/dist/socket-sdk-class.d.ts +7 -7
- package/dist/socket-sdk-class.js +96 -34
- package/dist/types.d.ts +26 -4
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,30 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
|
|
7
|
+
## [1.10.0](https://github.com/SocketDev/socket-sdk-js/releases/tag/v1.10.0) - 2025-10-04
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Added `PromiseQueue` utility for controlled concurrency in async operations
|
|
11
|
+
- HTTP retry logic with exponential backoff for improved reliability on transient failures
|
|
12
|
+
- Added option type interfaces: `CreateDependenciesSnapshotOptions`, `CreateOrgFullScanOptions`, `CreateScanFromFilepathsOptions`, `StreamOrgFullScanOptions`, `UploadManifestFilesOptions`
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- **BREAKING**: Refactored SDK methods to use options objects instead of positional parameters for better API clarity:
|
|
16
|
+
- `createDependenciesSnapshot(filepaths, options)` - replaced `repo` and `branch` positional parameters with options object
|
|
17
|
+
- `createOrgFullScan(orgSlug, filepaths, options)` - replaced positional parameters with options object
|
|
18
|
+
- `createScanFromFilepaths(filepaths, options)` - replaced positional parameters with options object
|
|
19
|
+
- `streamOrgFullScan(orgSlug, fullScanId, options)` - replaced positional parameters with options object
|
|
20
|
+
- `uploadManifestFiles(orgSlug, filepaths, options)` - replaced positional parameters with options object
|
|
21
|
+
- Improved type safety by replacing `any` types with `unknown` or `never` where appropriate
|
|
22
|
+
- Enhanced code style with numeric separators for better readability of large numbers
|
|
23
|
+
- Improved coverage reporting accuracy with c8 ignore comments
|
|
24
|
+
- Updated `@socketsecurity/registry` dependency to 1.4.0
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- Fixed import assertion syntax for JSON imports to use standard import syntax
|
|
28
|
+
- Fixed HTTP retry test mocks to correctly match PUT method requests
|
|
29
|
+
- Fixed critical issues in type handling and URL search parameter conversions
|
|
30
|
+
|
|
7
31
|
## [1.9.2](https://github.com/SocketDev/socket-sdk-js/releases/tag/v1.9.2) - 2025-10-04
|
|
8
32
|
|
|
9
33
|
### Changed
|
package/README.md
CHANGED
|
@@ -19,7 +19,11 @@ pnpm add @socketsecurity/sdk
|
|
|
19
19
|
```javascript
|
|
20
20
|
import { SocketSdk } from '@socketsecurity/sdk'
|
|
21
21
|
|
|
22
|
-
const client = new SocketSdk('yourApiKeyHere'
|
|
22
|
+
const client = new SocketSdk('yourApiKeyHere', {
|
|
23
|
+
retries: 3, // Retry failed requests up to 3 times (default: 3)
|
|
24
|
+
retryDelay: 1000, // Start with 1s delay, exponential backoff (default: 1000ms)
|
|
25
|
+
timeout: 30000, // Request timeout in milliseconds (optional)
|
|
26
|
+
})
|
|
23
27
|
|
|
24
28
|
const res = await client.getQuota()
|
|
25
29
|
|
|
@@ -29,6 +33,27 @@ if (res.success) {
|
|
|
29
33
|
}
|
|
30
34
|
```
|
|
31
35
|
|
|
36
|
+
### Configuration Options
|
|
37
|
+
|
|
38
|
+
The SDK constructor accepts the following options:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
interface SocketSdkOptions {
|
|
42
|
+
baseUrl?: string // API base URL (default: 'https://api.socket.dev/v0/')
|
|
43
|
+
timeout?: number // Request timeout in milliseconds
|
|
44
|
+
retries?: number // Number of retry attempts for failed requests (default: 3)
|
|
45
|
+
retryDelay?: number // Initial retry delay in ms, with exponential backoff (default: 1000)
|
|
46
|
+
userAgent?: string // Custom user agent string
|
|
47
|
+
agent?: Agent // Custom HTTP agent for advanced networking
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Retry Logic:**
|
|
52
|
+
- Automatically retries transient network errors and 5xx server responses
|
|
53
|
+
- Uses exponential backoff: 1s, 2s, 4s, 8s... (configurable via `retryDelay`)
|
|
54
|
+
- Does NOT retry 401/403 authentication errors (immediate failure)
|
|
55
|
+
- Set `retries: 0` to disable retry logic entirely
|
|
56
|
+
|
|
32
57
|
### Quota Management Example
|
|
33
58
|
|
|
34
59
|
```javascript
|
package/dist/constants.js
CHANGED
|
@@ -8,9 +8,6 @@ exports.publicPolicy = exports.httpAgentNames = exports.DEFAULT_USER_AGENT = voi
|
|
|
8
8
|
* @fileoverview Configuration constants and enums for the Socket SDK.
|
|
9
9
|
* Provides default values, HTTP agents, and public policy configurations for API interactions.
|
|
10
10
|
*/
|
|
11
|
-
// Import attributes are only supported when the '--module' option is set to
|
|
12
|
-
// 'esnext', 'node18', 'node20', 'nodenext', or 'preserve'.
|
|
13
|
-
// @ts-ignore: Avoid TS import attributes error.
|
|
14
11
|
const package_json_1 = __importDefault(require("../package.json"));
|
|
15
12
|
const user_agent_1 = require("./user-agent");
|
|
16
13
|
exports.DEFAULT_USER_AGENT = (0, user_agent_1.createUserAgentFromPkgJson)(package_json_1.default);
|
package/dist/file-upload.js
CHANGED
|
@@ -24,7 +24,7 @@ function createRequestBodyForFilepaths(filepaths, basePath) {
|
|
|
24
24
|
const filename = node_path_1.default.basename(absPath);
|
|
25
25
|
requestBody.push([
|
|
26
26
|
`Content-Disposition: form-data; name="${relPath}"; filename="${filename}"\r\n`,
|
|
27
|
-
|
|
27
|
+
'Content-Type: application/octet-stream\r\n\r\n',
|
|
28
28
|
(0, node_fs_1.createReadStream)(absPath, { highWaterMark: 1024 * 1024 }),
|
|
29
29
|
]);
|
|
30
30
|
}
|
|
@@ -39,7 +39,7 @@ function createRequestBodyForJson(jsonData, basename = 'data.json') {
|
|
|
39
39
|
const name = node_path_1.default.basename(basename, ext);
|
|
40
40
|
return [
|
|
41
41
|
`Content-Disposition: form-data; name="${name}"; filename="${basename}"\r\n` +
|
|
42
|
-
|
|
42
|
+
'Content-Type: application/json\r\n\r\n',
|
|
43
43
|
node_stream_1.Readable.from(JSON.stringify(jsonData), { highWaterMark: 1024 * 1024 }),
|
|
44
44
|
'\r\n',
|
|
45
45
|
];
|
package/dist/http-client.d.ts
CHANGED
|
@@ -75,4 +75,39 @@ export declare function isResponseOk(response: IncomingMessage): boolean;
|
|
|
75
75
|
* Transform artifact data based on authentication status.
|
|
76
76
|
* Filters and compacts response data for public/free-tier users.
|
|
77
77
|
*/
|
|
78
|
-
export declare function reshapeArtifactForPublicPolicy<T extends Record<string,
|
|
78
|
+
export declare function reshapeArtifactForPublicPolicy<T extends Record<string, unknown>>(data: T, isAuthenticated: boolean, actions?: string | undefined): T;
|
|
79
|
+
/**
|
|
80
|
+
* Retry helper for HTTP requests with exponential backoff.
|
|
81
|
+
* Wraps any async HTTP function and retries on failure.
|
|
82
|
+
*
|
|
83
|
+
* @param fn - Async function to retry
|
|
84
|
+
* @param retries - Number of retry attempts (default: 3)
|
|
85
|
+
* @param retryDelay - Initial delay in ms (default: 1000)
|
|
86
|
+
* @returns Result of the function call
|
|
87
|
+
* @throws {Error} Last error if all retries exhausted
|
|
88
|
+
*/
|
|
89
|
+
export declare function withRetry<T>(fn: () => Promise<T>, retries?: number, retryDelay?: number): Promise<T>;
|
|
90
|
+
/**
|
|
91
|
+
* Create GET request with automatic retry logic.
|
|
92
|
+
* Retries on network errors and 5xx responses.
|
|
93
|
+
*
|
|
94
|
+
* @param retries - Number of retry attempts (default: 3)
|
|
95
|
+
* @param retryDelay - Initial delay in ms (default: 1000)
|
|
96
|
+
*/
|
|
97
|
+
export declare function createGetRequestWithRetry(baseUrl: string, urlPath: string, options: RequestOptions, retries?: number, retryDelay?: number): Promise<IncomingMessage>;
|
|
98
|
+
/**
|
|
99
|
+
* Create DELETE request with automatic retry logic.
|
|
100
|
+
* Retries on network errors and 5xx responses.
|
|
101
|
+
*
|
|
102
|
+
* @param retries - Number of retry attempts (default: 3)
|
|
103
|
+
* @param retryDelay - Initial delay in ms (default: 1000)
|
|
104
|
+
*/
|
|
105
|
+
export declare function createDeleteRequestWithRetry(baseUrl: string, urlPath: string, options: RequestOptions, retries?: number, retryDelay?: number): Promise<IncomingMessage>;
|
|
106
|
+
/**
|
|
107
|
+
* Create request with JSON payload and automatic retry logic.
|
|
108
|
+
* Retries on network errors and 5xx responses.
|
|
109
|
+
*
|
|
110
|
+
* @param retries - Number of retry attempts (default: 3)
|
|
111
|
+
* @param retryDelay - Initial delay in ms (default: 1000)
|
|
112
|
+
*/
|
|
113
|
+
export declare function createRequestWithJsonAndRetry(method: SendMethod, baseUrl: string, urlPath: string, json: unknown, options: RequestOptions, retries?: number, retryDelay?: number): Promise<IncomingMessage>;
|
package/dist/http-client.js
CHANGED
|
@@ -13,6 +13,10 @@ exports.getResponse = getResponse;
|
|
|
13
13
|
exports.getResponseJson = getResponseJson;
|
|
14
14
|
exports.isResponseOk = isResponseOk;
|
|
15
15
|
exports.reshapeArtifactForPublicPolicy = reshapeArtifactForPublicPolicy;
|
|
16
|
+
exports.withRetry = withRetry;
|
|
17
|
+
exports.createGetRequestWithRetry = createGetRequestWithRetry;
|
|
18
|
+
exports.createDeleteRequestWithRetry = createDeleteRequestWithRetry;
|
|
19
|
+
exports.createRequestWithJsonAndRetry = createRequestWithJsonAndRetry;
|
|
16
20
|
/**
|
|
17
21
|
* @fileoverview HTTP client utilities for Socket API communication.
|
|
18
22
|
* Provides low-level HTTP request handling with proper error management and response parsing.
|
|
@@ -248,12 +252,15 @@ function reshapeArtifactForPublicPolicy(data, isAuthenticated, actions) {
|
|
|
248
252
|
// Handle both single artifacts and objects with artifacts arrays.
|
|
249
253
|
if (data['artifacts']) {
|
|
250
254
|
// Object with artifacts array.
|
|
255
|
+
const artifacts = data['artifacts'];
|
|
251
256
|
return {
|
|
252
257
|
...data,
|
|
253
|
-
artifacts:
|
|
258
|
+
artifacts: Array.isArray(artifacts)
|
|
259
|
+
? artifacts.map(reshapeArtifact)
|
|
260
|
+
: artifacts,
|
|
254
261
|
};
|
|
255
262
|
}
|
|
256
|
-
|
|
263
|
+
if (data['alerts']) {
|
|
257
264
|
// Single artifact with alerts.
|
|
258
265
|
return reshapeArtifact(data);
|
|
259
266
|
}
|
|
@@ -261,3 +268,80 @@ function reshapeArtifactForPublicPolicy(data, isAuthenticated, actions) {
|
|
|
261
268
|
return data;
|
|
262
269
|
/* c8 ignore stop */
|
|
263
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Retry helper for HTTP requests with exponential backoff.
|
|
273
|
+
* Wraps any async HTTP function and retries on failure.
|
|
274
|
+
*
|
|
275
|
+
* @param fn - Async function to retry
|
|
276
|
+
* @param retries - Number of retry attempts (default: 3)
|
|
277
|
+
* @param retryDelay - Initial delay in ms (default: 1000)
|
|
278
|
+
* @returns Result of the function call
|
|
279
|
+
* @throws {Error} Last error if all retries exhausted
|
|
280
|
+
*/
|
|
281
|
+
async function withRetry(fn, retries = 3, retryDelay = 1000) {
|
|
282
|
+
let lastError;
|
|
283
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
284
|
+
try {
|
|
285
|
+
// eslint-disable-next-line no-await-in-loop
|
|
286
|
+
return await fn();
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
lastError = error;
|
|
290
|
+
// Last attempt - throw error with retry context.
|
|
291
|
+
if (attempt === retries) {
|
|
292
|
+
const enhancedError = new Error(`Request failed after ${retries + 1} attempts`, { cause: lastError });
|
|
293
|
+
throw enhancedError;
|
|
294
|
+
}
|
|
295
|
+
// Check if error is retryable (network errors, 5xx responses).
|
|
296
|
+
if (error instanceof ResponseError) {
|
|
297
|
+
const status = error.response.statusCode;
|
|
298
|
+
// Don't retry client errors (4xx).
|
|
299
|
+
if (status && status >= 400 && status < 500) {
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
302
|
+
(0, debug_1.debugLog)('withRetry', `Retrying after ${status} error (attempt ${attempt + 1}/${retries + 1})`);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
(0, debug_1.debugLog)('withRetry', `Retrying after network error (attempt ${attempt + 1}/${retries + 1})`);
|
|
306
|
+
}
|
|
307
|
+
// Exponential backoff.
|
|
308
|
+
const delayMs = retryDelay * 2 ** attempt;
|
|
309
|
+
(0, debug_1.debugLog)('withRetry', `Waiting ${delayMs}ms before retry`);
|
|
310
|
+
// eslint-disable-next-line no-await-in-loop
|
|
311
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// Fallback error if lastError is somehow undefined.
|
|
315
|
+
/* c8 ignore next - Defensive fallback for undefined lastError */
|
|
316
|
+
throw lastError || new Error('Request failed after retries');
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Create GET request with automatic retry logic.
|
|
320
|
+
* Retries on network errors and 5xx responses.
|
|
321
|
+
*
|
|
322
|
+
* @param retries - Number of retry attempts (default: 3)
|
|
323
|
+
* @param retryDelay - Initial delay in ms (default: 1000)
|
|
324
|
+
*/
|
|
325
|
+
async function createGetRequestWithRetry(baseUrl, urlPath, options, retries = 3, retryDelay = 1000) {
|
|
326
|
+
return await withRetry(() => createGetRequest(baseUrl, urlPath, options), retries, retryDelay);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Create DELETE request with automatic retry logic.
|
|
330
|
+
* Retries on network errors and 5xx responses.
|
|
331
|
+
*
|
|
332
|
+
* @param retries - Number of retry attempts (default: 3)
|
|
333
|
+
* @param retryDelay - Initial delay in ms (default: 1000)
|
|
334
|
+
*/
|
|
335
|
+
async function createDeleteRequestWithRetry(baseUrl, urlPath, options, retries = 3, retryDelay = 1000) {
|
|
336
|
+
return await withRetry(() => createDeleteRequest(baseUrl, urlPath, options), retries, retryDelay);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Create request with JSON payload and automatic retry logic.
|
|
340
|
+
* Retries on network errors and 5xx responses.
|
|
341
|
+
*
|
|
342
|
+
* @param retries - Number of retry attempts (default: 3)
|
|
343
|
+
* @param retryDelay - Initial delay in ms (default: 1000)
|
|
344
|
+
*/
|
|
345
|
+
async function createRequestWithJsonAndRetry(method, baseUrl, urlPath, json, options, retries = 3, retryDelay = 1000) {
|
|
346
|
+
return await withRetry(() => createRequestWithJson(method, baseUrl, urlPath, json, options), retries, retryDelay);
|
|
347
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { DEFAULT_USER_AGENT, httpAgentNames, publicPolicy } from './constants';
|
|
6
6
|
import { normalizeBaseUrl, promiseWithResolvers, queryToSearchParams, resolveAbsPaths, resolveBasePath } from './utils';
|
|
7
|
-
export type * from './types';
|
|
8
|
-
export { createUserAgentFromPkgJson } from './user-agent';
|
|
9
|
-
export { createDeleteRequest, createGetRequest, createRequestWithJson, getErrorResponseBody, getHttpModule, getResponse, getResponseJson, isResponseOk, reshapeArtifactForPublicPolicy, ResponseError, } from './http-client';
|
|
10
7
|
export { createRequestBodyForFilepaths, createRequestBodyForJson, createUploadRequest, } from './file-upload';
|
|
11
|
-
export {
|
|
8
|
+
export { createDeleteRequest, createGetRequest, createRequestWithJson, getErrorResponseBody, getHttpModule, getResponse, getResponseJson, isResponseOk, ResponseError, reshapeArtifactForPublicPolicy, } from './http-client';
|
|
12
9
|
export { calculateTotalQuotaCost, getAllMethodRequirements, getMethodRequirements, getMethodsByPermissions, getMethodsByQuotaCost, getQuotaCost, getQuotaUsageSummary, getRequiredPermissions, hasQuotaForMethods, } from './quota-utils';
|
|
10
|
+
export { SocketSdk } from './socket-sdk-class';
|
|
11
|
+
export type * from './types';
|
|
12
|
+
export { createUserAgentFromPkgJson } from './user-agent';
|
|
13
13
|
export { normalizeBaseUrl, promiseWithResolvers, queryToSearchParams, resolveAbsPaths, resolveBasePath, };
|
|
14
14
|
export { DEFAULT_USER_AGENT, httpAgentNames, publicPolicy };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.publicPolicy = exports.httpAgentNames = exports.DEFAULT_USER_AGENT = exports.resolveBasePath = exports.resolveAbsPaths = exports.queryToSearchParams = exports.promiseWithResolvers = exports.normalizeBaseUrl = exports.
|
|
3
|
+
exports.publicPolicy = exports.httpAgentNames = exports.DEFAULT_USER_AGENT = exports.resolveBasePath = exports.resolveAbsPaths = exports.queryToSearchParams = exports.promiseWithResolvers = exports.normalizeBaseUrl = exports.createUserAgentFromPkgJson = exports.SocketSdk = exports.hasQuotaForMethods = exports.getRequiredPermissions = exports.getQuotaUsageSummary = exports.getQuotaCost = exports.getMethodsByQuotaCost = exports.getMethodsByPermissions = exports.getMethodRequirements = exports.getAllMethodRequirements = exports.calculateTotalQuotaCost = exports.reshapeArtifactForPublicPolicy = exports.ResponseError = exports.isResponseOk = exports.getResponseJson = exports.getResponse = exports.getHttpModule = exports.getErrorResponseBody = exports.createRequestWithJson = exports.createGetRequest = exports.createDeleteRequest = exports.createUploadRequest = exports.createRequestBodyForJson = exports.createRequestBodyForFilepaths = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* @fileoverview Main entry point for the Socket SDK.
|
|
6
6
|
* Provides the SocketSdk class and utility functions for Socket security analysis API interactions.
|
|
@@ -16,9 +16,11 @@ Object.defineProperty(exports, "promiseWithResolvers", { enumerable: true, get:
|
|
|
16
16
|
Object.defineProperty(exports, "queryToSearchParams", { enumerable: true, get: function () { return utils_1.queryToSearchParams; } });
|
|
17
17
|
Object.defineProperty(exports, "resolveAbsPaths", { enumerable: true, get: function () { return utils_1.resolveAbsPaths; } });
|
|
18
18
|
Object.defineProperty(exports, "resolveBasePath", { enumerable: true, get: function () { return utils_1.resolveBasePath; } });
|
|
19
|
-
// Re-export
|
|
20
|
-
const
|
|
21
|
-
Object.defineProperty(exports, "
|
|
19
|
+
// Re-export file upload functions
|
|
20
|
+
const file_upload_1 = require("./file-upload");
|
|
21
|
+
Object.defineProperty(exports, "createRequestBodyForFilepaths", { enumerable: true, get: function () { return file_upload_1.createRequestBodyForFilepaths; } });
|
|
22
|
+
Object.defineProperty(exports, "createRequestBodyForJson", { enumerable: true, get: function () { return file_upload_1.createRequestBodyForJson; } });
|
|
23
|
+
Object.defineProperty(exports, "createUploadRequest", { enumerable: true, get: function () { return file_upload_1.createUploadRequest; } });
|
|
22
24
|
// Re-export HTTP client functions
|
|
23
25
|
const http_client_1 = require("./http-client");
|
|
24
26
|
Object.defineProperty(exports, "createDeleteRequest", { enumerable: true, get: function () { return http_client_1.createDeleteRequest; } });
|
|
@@ -29,16 +31,8 @@ Object.defineProperty(exports, "getHttpModule", { enumerable: true, get: functio
|
|
|
29
31
|
Object.defineProperty(exports, "getResponse", { enumerable: true, get: function () { return http_client_1.getResponse; } });
|
|
30
32
|
Object.defineProperty(exports, "getResponseJson", { enumerable: true, get: function () { return http_client_1.getResponseJson; } });
|
|
31
33
|
Object.defineProperty(exports, "isResponseOk", { enumerable: true, get: function () { return http_client_1.isResponseOk; } });
|
|
32
|
-
Object.defineProperty(exports, "reshapeArtifactForPublicPolicy", { enumerable: true, get: function () { return http_client_1.reshapeArtifactForPublicPolicy; } });
|
|
33
34
|
Object.defineProperty(exports, "ResponseError", { enumerable: true, get: function () { return http_client_1.ResponseError; } });
|
|
34
|
-
|
|
35
|
-
const file_upload_1 = require("./file-upload");
|
|
36
|
-
Object.defineProperty(exports, "createRequestBodyForFilepaths", { enumerable: true, get: function () { return file_upload_1.createRequestBodyForFilepaths; } });
|
|
37
|
-
Object.defineProperty(exports, "createRequestBodyForJson", { enumerable: true, get: function () { return file_upload_1.createRequestBodyForJson; } });
|
|
38
|
-
Object.defineProperty(exports, "createUploadRequest", { enumerable: true, get: function () { return file_upload_1.createUploadRequest; } });
|
|
39
|
-
// Re-export the main SocketSdk class
|
|
40
|
-
const socket_sdk_class_1 = require("./socket-sdk-class");
|
|
41
|
-
Object.defineProperty(exports, "SocketSdk", { enumerable: true, get: function () { return socket_sdk_class_1.SocketSdk; } });
|
|
35
|
+
Object.defineProperty(exports, "reshapeArtifactForPublicPolicy", { enumerable: true, get: function () { return http_client_1.reshapeArtifactForPublicPolicy; } });
|
|
42
36
|
// Re-export quota utility functions
|
|
43
37
|
const quota_utils_1 = require("./quota-utils");
|
|
44
38
|
Object.defineProperty(exports, "calculateTotalQuotaCost", { enumerable: true, get: function () { return quota_utils_1.calculateTotalQuotaCost; } });
|
|
@@ -50,3 +44,9 @@ Object.defineProperty(exports, "getQuotaCost", { enumerable: true, get: function
|
|
|
50
44
|
Object.defineProperty(exports, "getQuotaUsageSummary", { enumerable: true, get: function () { return quota_utils_1.getQuotaUsageSummary; } });
|
|
51
45
|
Object.defineProperty(exports, "getRequiredPermissions", { enumerable: true, get: function () { return quota_utils_1.getRequiredPermissions; } });
|
|
52
46
|
Object.defineProperty(exports, "hasQuotaForMethods", { enumerable: true, get: function () { return quota_utils_1.hasQuotaForMethods; } });
|
|
47
|
+
// Re-export the main SocketSdk class
|
|
48
|
+
const socket_sdk_class_1 = require("./socket-sdk-class");
|
|
49
|
+
Object.defineProperty(exports, "SocketSdk", { enumerable: true, get: function () { return socket_sdk_class_1.SocketSdk; } });
|
|
50
|
+
// Re-export functions from modules
|
|
51
|
+
const user_agent_1 = require("./user-agent");
|
|
52
|
+
Object.defineProperty(exports, "createUserAgentFromPkgJson", { enumerable: true, get: function () { return user_agent_1.createUserAgentFromPkgJson; } });
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare class PromiseQueue {
|
|
2
|
+
private queue;
|
|
3
|
+
private running;
|
|
4
|
+
private readonly maxConcurrency;
|
|
5
|
+
private readonly maxQueueLength;
|
|
6
|
+
/**
|
|
7
|
+
* Creates a new PromiseQueue
|
|
8
|
+
* @param maxConcurrency - Maximum number of promises that can run concurrently
|
|
9
|
+
* @param maxQueueLength - Maximum queue size (older tasks are dropped if exceeded)
|
|
10
|
+
*/
|
|
11
|
+
constructor(maxConcurrency: number, maxQueueLength?: number | undefined);
|
|
12
|
+
/**
|
|
13
|
+
* Add a task to the queue
|
|
14
|
+
* @param fn - Async function to execute
|
|
15
|
+
* @returns Promise that resolves with the function's result
|
|
16
|
+
*/
|
|
17
|
+
add<T>(fn: () => Promise<T>): Promise<T>;
|
|
18
|
+
private runNext;
|
|
19
|
+
/**
|
|
20
|
+
* Wait for all queued and running tasks to complete
|
|
21
|
+
*/
|
|
22
|
+
onIdle(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Get the number of tasks currently running
|
|
25
|
+
*/
|
|
26
|
+
get activeCount(): number;
|
|
27
|
+
/**
|
|
28
|
+
* Get the number of tasks waiting in the queue
|
|
29
|
+
*/
|
|
30
|
+
get pendingCount(): number;
|
|
31
|
+
/**
|
|
32
|
+
* Clear all pending tasks from the queue (does not affect running tasks)
|
|
33
|
+
*/
|
|
34
|
+
clear(): void;
|
|
35
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PromiseQueue = void 0;
|
|
4
|
+
class PromiseQueue {
|
|
5
|
+
queue = [];
|
|
6
|
+
running = 0;
|
|
7
|
+
maxConcurrency;
|
|
8
|
+
maxQueueLength;
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new PromiseQueue
|
|
11
|
+
* @param maxConcurrency - Maximum number of promises that can run concurrently
|
|
12
|
+
* @param maxQueueLength - Maximum queue size (older tasks are dropped if exceeded)
|
|
13
|
+
*/
|
|
14
|
+
constructor(maxConcurrency, maxQueueLength) {
|
|
15
|
+
this.maxConcurrency = maxConcurrency;
|
|
16
|
+
this.maxQueueLength = maxQueueLength;
|
|
17
|
+
if (maxConcurrency < 1) {
|
|
18
|
+
throw new Error('maxConcurrency must be at least 1');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Add a task to the queue
|
|
23
|
+
* @param fn - Async function to execute
|
|
24
|
+
* @returns Promise that resolves with the function's result
|
|
25
|
+
*/
|
|
26
|
+
async add(fn) {
|
|
27
|
+
return await new Promise((resolve, reject) => {
|
|
28
|
+
const task = { fn, resolve, reject };
|
|
29
|
+
if (this.maxQueueLength && this.queue.length >= this.maxQueueLength) {
|
|
30
|
+
// Drop oldest task to prevent memory buildup
|
|
31
|
+
this.queue.shift();
|
|
32
|
+
}
|
|
33
|
+
this.queue.push(task);
|
|
34
|
+
this.runNext();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
runNext() {
|
|
38
|
+
if (this.running >= this.maxConcurrency || this.queue.length === 0) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const task = this.queue.shift();
|
|
42
|
+
/* c8 ignore next 3 - Defensive check; unreachable since we verify queue.length above */
|
|
43
|
+
if (!task) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.running++;
|
|
47
|
+
task
|
|
48
|
+
.fn()
|
|
49
|
+
.then(task.resolve)
|
|
50
|
+
.catch(task.reject)
|
|
51
|
+
.finally(() => {
|
|
52
|
+
this.running--;
|
|
53
|
+
this.runNext();
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Wait for all queued and running tasks to complete
|
|
58
|
+
*/
|
|
59
|
+
async onIdle() {
|
|
60
|
+
return await new Promise(resolve => {
|
|
61
|
+
const check = () => {
|
|
62
|
+
if (this.running === 0 && this.queue.length === 0) {
|
|
63
|
+
resolve();
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
setImmediate(check);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
check();
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get the number of tasks currently running
|
|
74
|
+
*/
|
|
75
|
+
get activeCount() {
|
|
76
|
+
return this.running;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get the number of tasks waiting in the queue
|
|
80
|
+
*/
|
|
81
|
+
get pendingCount() {
|
|
82
|
+
return this.queue.length;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Clear all pending tasks from the queue (does not affect running tasks)
|
|
86
|
+
*/
|
|
87
|
+
clear() {
|
|
88
|
+
this.queue = [];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.PromiseQueue = PromiseQueue;
|
package/dist/quota-utils.js
CHANGED
|
@@ -22,8 +22,11 @@ function loadRequirements() {
|
|
|
22
22
|
return requirements;
|
|
23
23
|
}
|
|
24
24
|
try {
|
|
25
|
-
// Resolve path relative to
|
|
26
|
-
|
|
25
|
+
// Resolve path relative to this module file location.
|
|
26
|
+
// When compiled, __dirname will point to dist/ directory.
|
|
27
|
+
// In source, __dirname points to src/ directory.
|
|
28
|
+
// requirements.json is always in the parent directory of dist/ or src/.
|
|
29
|
+
const requirementsPath = (0, node_path_1.join)(__dirname, '..', 'requirements.json');
|
|
27
30
|
const data = (0, node_fs_1.readFileSync)(requirementsPath, 'utf8');
|
|
28
31
|
requirements = JSON.parse(data);
|
|
29
32
|
return requirements;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ArtifactPatches, BatchPackageFetchResultType, BatchPackageStreamOptions, Entitlement, GetOptions, PatchViewResponse, QueryParams, SendOptions, SocketSdkGenericResult, SocketSdkOptions, SocketSdkResult, UploadManifestFilesError, UploadManifestFilesReturnType } from './types';
|
|
1
|
+
import type { ArtifactPatches, BatchPackageFetchResultType, BatchPackageStreamOptions, CreateDependenciesSnapshotOptions, CreateOrgFullScanOptions, CreateScanFromFilepathsOptions, Entitlement, GetOptions, PatchViewResponse, QueryParams, SendOptions, SocketSdkGenericResult, SocketSdkOptions, SocketSdkResult, StreamOrgFullScanOptions, UploadManifestFilesError, UploadManifestFilesOptions, UploadManifestFilesReturnType } from './types';
|
|
2
2
|
import type { IncomingMessage } from 'node:http';
|
|
3
3
|
/**
|
|
4
4
|
* Socket SDK for programmatic access to Socket.dev security analysis APIs.
|
|
@@ -8,7 +8,7 @@ export declare class SocketSdk {
|
|
|
8
8
|
#private;
|
|
9
9
|
/**
|
|
10
10
|
* Initialize Socket SDK with API token and configuration options.
|
|
11
|
-
* Sets up authentication, base URL,
|
|
11
|
+
* Sets up authentication, base URL, HTTP client options, and retry behavior.
|
|
12
12
|
*/
|
|
13
13
|
constructor(apiToken: string, options?: SocketSdkOptions | undefined);
|
|
14
14
|
/**
|
|
@@ -39,7 +39,7 @@ export declare class SocketSdk {
|
|
|
39
39
|
*
|
|
40
40
|
* @throws {Error} When server returns 5xx status codes
|
|
41
41
|
*/
|
|
42
|
-
createDependenciesSnapshot(filepaths: string[],
|
|
42
|
+
createDependenciesSnapshot(filepaths: string[], options?: CreateDependenciesSnapshotOptions | undefined): Promise<SocketSdkResult<'createDependenciesSnapshot'>>;
|
|
43
43
|
/**
|
|
44
44
|
* Create a diff scan from two full scan IDs.
|
|
45
45
|
* Compares two existing full scans to identify changes.
|
|
@@ -53,7 +53,7 @@ export declare class SocketSdk {
|
|
|
53
53
|
*
|
|
54
54
|
* @throws {Error} When server returns 5xx status codes
|
|
55
55
|
*/
|
|
56
|
-
createOrgFullScan(orgSlug: string, filepaths: string[],
|
|
56
|
+
createOrgFullScan(orgSlug: string, filepaths: string[], options?: CreateOrgFullScanOptions | undefined): Promise<SocketSdkResult<'CreateOrgFullScan'>>;
|
|
57
57
|
/**
|
|
58
58
|
* Create a new repository in an organization.
|
|
59
59
|
* Registers a repository for monitoring and security scanning.
|
|
@@ -74,7 +74,7 @@ export declare class SocketSdk {
|
|
|
74
74
|
*
|
|
75
75
|
* @throws {Error} When server returns 5xx status codes
|
|
76
76
|
*/
|
|
77
|
-
createScanFromFilepaths(filepaths: string[],
|
|
77
|
+
createScanFromFilepaths(filepaths: string[], options?: CreateScanFromFilepathsOptions | undefined): Promise<SocketSdkResult<'createReport'>>;
|
|
78
78
|
/**
|
|
79
79
|
* Delete a diff scan from an organization.
|
|
80
80
|
* Permanently removes diff scan data and results.
|
|
@@ -362,7 +362,7 @@ export declare class SocketSdk {
|
|
|
362
362
|
*
|
|
363
363
|
* @throws {Error} When server returns 5xx status codes
|
|
364
364
|
*/
|
|
365
|
-
streamOrgFullScan(orgSlug: string, fullScanId: string,
|
|
365
|
+
streamOrgFullScan(orgSlug: string, fullScanId: string, options?: StreamOrgFullScanOptions | undefined): Promise<SocketSdkResult<'getOrgFullScan'>>;
|
|
366
366
|
/**
|
|
367
367
|
* Stream patches for artifacts in a scan report.
|
|
368
368
|
*
|
|
@@ -411,7 +411,7 @@ export declare class SocketSdk {
|
|
|
411
411
|
*
|
|
412
412
|
* @throws {Error} When server returns 5xx status codes
|
|
413
413
|
*/
|
|
414
|
-
uploadManifestFiles(orgSlug: string, filepaths: string[],
|
|
414
|
+
uploadManifestFiles(orgSlug: string, filepaths: string[], options?: UploadManifestFilesOptions | undefined): Promise<UploadManifestFilesReturnType | UploadManifestFilesError>;
|
|
415
415
|
/**
|
|
416
416
|
* View detailed information about a specific patch by its UUID.
|
|
417
417
|
*
|
package/dist/socket-sdk-class.js
CHANGED
|
@@ -31,12 +31,14 @@ class SocketSdk {
|
|
|
31
31
|
#apiToken;
|
|
32
32
|
#baseUrl;
|
|
33
33
|
#reqOptions;
|
|
34
|
+
#retries;
|
|
35
|
+
#retryDelay;
|
|
34
36
|
/**
|
|
35
37
|
* Initialize Socket SDK with API token and configuration options.
|
|
36
|
-
* Sets up authentication, base URL,
|
|
38
|
+
* Sets up authentication, base URL, HTTP client options, and retry behavior.
|
|
37
39
|
*/
|
|
38
40
|
constructor(apiToken, options) {
|
|
39
|
-
const { agent: agentOrObj, baseUrl = 'https://api.socket.dev/v0/', timeout, userAgent, } = { __proto__: null, ...options };
|
|
41
|
+
const { agent: agentOrObj, baseUrl = 'https://api.socket.dev/v0/', retries = 3, retryDelay = 1000, timeout, userAgent, } = { __proto__: null, ...options };
|
|
40
42
|
const agentKeys = agentOrObj ? Object.keys(agentOrObj) : [];
|
|
41
43
|
const agentAsGotOptions = agentOrObj;
|
|
42
44
|
const agent = (agentKeys.length && agentKeys.every(k => constants_1.httpAgentNames.has(k))
|
|
@@ -47,6 +49,8 @@ class SocketSdk {
|
|
|
47
49
|
: agentOrObj);
|
|
48
50
|
this.#apiToken = apiToken;
|
|
49
51
|
this.#baseUrl = (0, utils_1.normalizeBaseUrl)(baseUrl);
|
|
52
|
+
this.#retries = retries;
|
|
53
|
+
this.#retryDelay = retryDelay;
|
|
50
54
|
this.#reqOptions = {
|
|
51
55
|
...(agent ? { agent } : {}),
|
|
52
56
|
headers: {
|
|
@@ -57,6 +61,33 @@ class SocketSdk {
|
|
|
57
61
|
...(timeout ? { timeout } : {}),
|
|
58
62
|
};
|
|
59
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Execute an HTTP request with retry logic.
|
|
66
|
+
* Internal method for wrapping HTTP operations with exponential backoff.
|
|
67
|
+
*/
|
|
68
|
+
async #executeWithRetry(operation) {
|
|
69
|
+
const result = await (0, promises_1.pRetry)(operation, {
|
|
70
|
+
baseDelayMs: this.#retryDelay,
|
|
71
|
+
onRetry(_attempt, error) {
|
|
72
|
+
/* c8 ignore next 3 - Early return for non-ResponseError types in retry logic */
|
|
73
|
+
if (!(error instanceof http_client_1.ResponseError)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const { statusCode } = error.response;
|
|
77
|
+
// Don't retry authentication/authorization errors - they won't succeed.
|
|
78
|
+
if (statusCode === 401 || statusCode === 403) {
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
onRetryRethrow: true,
|
|
83
|
+
retries: this.#retries,
|
|
84
|
+
});
|
|
85
|
+
/* c8 ignore next 3 - Defensive check for undefined result from pRetry abort */
|
|
86
|
+
if (result === undefined) {
|
|
87
|
+
throw new Error('Request aborted');
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
60
91
|
/**
|
|
61
92
|
* Create async generator for streaming batch package URL processing.
|
|
62
93
|
* Internal method for handling chunked PURL responses with error handling.
|
|
@@ -64,30 +95,21 @@ class SocketSdk {
|
|
|
64
95
|
async *#createBatchPurlGenerator(componentsObj, queryParams) {
|
|
65
96
|
let res;
|
|
66
97
|
try {
|
|
67
|
-
res = await (
|
|
68
|
-
retries: 4,
|
|
69
|
-
onRetryRethrow: true,
|
|
70
|
-
onRetry(_attempt, error) {
|
|
71
|
-
/* c8 ignore next 3 - Early return for non-ResponseError types in retry logic, difficult to test without complex network error simulation. */
|
|
72
|
-
if (!(error instanceof http_client_1.ResponseError)) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
const { statusCode } = error.response;
|
|
76
|
-
// Don't retry authentication/authorization errors - they won't succeed.
|
|
77
|
-
if (statusCode === 401 || statusCode === 403) {
|
|
78
|
-
throw error;
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
});
|
|
98
|
+
res = await this.#executeWithRetry(() => this.#createBatchPurlRequest(componentsObj, queryParams));
|
|
82
99
|
}
|
|
83
100
|
catch (e) {
|
|
84
101
|
yield await this.#handleApiError(e);
|
|
85
102
|
return;
|
|
86
103
|
}
|
|
104
|
+
// Validate response before processing.
|
|
105
|
+
/* c8 ignore next 3 - Defensive check, response should always be defined after successful request */
|
|
106
|
+
if (!res) {
|
|
107
|
+
throw new Error('Failed to get response from batch PURL request');
|
|
108
|
+
}
|
|
87
109
|
// Parse the newline delimited JSON response.
|
|
88
110
|
const rli = node_readline_1.default.createInterface({
|
|
89
111
|
input: res,
|
|
90
|
-
crlfDelay:
|
|
112
|
+
crlfDelay: Number.POSITIVE_INFINITY,
|
|
91
113
|
signal: abort_signal_1.default,
|
|
92
114
|
});
|
|
93
115
|
const isPublicToken = this.#apiToken === SOCKET_PUBLIC_API_TOKEN_1.default;
|
|
@@ -285,10 +307,15 @@ class SocketSdk {
|
|
|
285
307
|
catch (e) {
|
|
286
308
|
return await this.#handleApiError(e);
|
|
287
309
|
}
|
|
310
|
+
// Validate response before processing.
|
|
311
|
+
/* c8 ignore next 3 - Defensive check, response should always be defined after successful request */
|
|
312
|
+
if (!res) {
|
|
313
|
+
throw new Error('Failed to get response from batch PURL request');
|
|
314
|
+
}
|
|
288
315
|
// Parse the newline delimited JSON response.
|
|
289
316
|
const rli = node_readline_1.default.createInterface({
|
|
290
317
|
input: res,
|
|
291
|
-
crlfDelay:
|
|
318
|
+
crlfDelay: Number.POSITIVE_INFINITY,
|
|
292
319
|
signal: abort_signal_1.default,
|
|
293
320
|
});
|
|
294
321
|
const isPublicToken = this.#apiToken === SOCKET_PUBLIC_API_TOKEN_1.default;
|
|
@@ -365,9 +392,13 @@ class SocketSdk {
|
|
|
365
392
|
while (running.length > 0) {
|
|
366
393
|
// eslint-disable-next-line no-await-in-loop
|
|
367
394
|
const { generator, iteratorResult } = await Promise.race(running.map(entry => entry.promise));
|
|
368
|
-
// Remove generator.
|
|
369
|
-
|
|
370
|
-
|
|
395
|
+
// Remove generator with safe index lookup.
|
|
396
|
+
const index = running.findIndex(entry => entry.generator === generator);
|
|
397
|
+
/* c8 ignore next 3 - Defensive check for concurrent generator cleanup edge case. */
|
|
398
|
+
if (index === -1) {
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
running.splice(index, 1);
|
|
371
402
|
// Yield the value if one is given, even when done:true.
|
|
372
403
|
if (iteratorResult.value) {
|
|
373
404
|
yield iteratorResult.value;
|
|
@@ -394,11 +425,15 @@ class SocketSdk {
|
|
|
394
425
|
*
|
|
395
426
|
* @throws {Error} When server returns 5xx status codes
|
|
396
427
|
*/
|
|
397
|
-
async createDependenciesSnapshot(filepaths,
|
|
428
|
+
async createDependenciesSnapshot(filepaths, options) {
|
|
429
|
+
const { pathsRelativeTo = '.', queryParams } = {
|
|
430
|
+
__proto__: null,
|
|
431
|
+
...options,
|
|
432
|
+
};
|
|
398
433
|
const basePath = (0, utils_1.resolveBasePath)(pathsRelativeTo);
|
|
399
434
|
const absFilepaths = (0, utils_1.resolveAbsPaths)(filepaths, basePath);
|
|
400
435
|
try {
|
|
401
|
-
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));
|
|
436
|
+
const data = await this.#executeWithRetry(async () => 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)));
|
|
402
437
|
return this.#handleApiSuccess(data);
|
|
403
438
|
}
|
|
404
439
|
catch (e) {
|
|
@@ -426,7 +461,11 @@ class SocketSdk {
|
|
|
426
461
|
*
|
|
427
462
|
* @throws {Error} When server returns 5xx status codes
|
|
428
463
|
*/
|
|
429
|
-
async createOrgFullScan(orgSlug, filepaths,
|
|
464
|
+
async createOrgFullScan(orgSlug, filepaths, options) {
|
|
465
|
+
const { pathsRelativeTo = '.', queryParams } = {
|
|
466
|
+
__proto__: null,
|
|
467
|
+
...options,
|
|
468
|
+
};
|
|
430
469
|
const basePath = (0, utils_1.resolveBasePath)(pathsRelativeTo);
|
|
431
470
|
const absFilepaths = (0, utils_1.resolveAbsPaths)(filepaths, basePath);
|
|
432
471
|
try {
|
|
@@ -473,7 +512,11 @@ class SocketSdk {
|
|
|
473
512
|
*
|
|
474
513
|
* @throws {Error} When server returns 5xx status codes
|
|
475
514
|
*/
|
|
476
|
-
async createScanFromFilepaths(filepaths,
|
|
515
|
+
async createScanFromFilepaths(filepaths, options) {
|
|
516
|
+
const { issueRules, pathsRelativeTo = '.' } = {
|
|
517
|
+
__proto__: null,
|
|
518
|
+
...options,
|
|
519
|
+
};
|
|
477
520
|
const basePath = (0, utils_1.resolveBasePath)(pathsRelativeTo);
|
|
478
521
|
const absFilepaths = (0, utils_1.resolveAbsPaths)(filepaths, basePath);
|
|
479
522
|
try {
|
|
@@ -769,7 +812,7 @@ class SocketSdk {
|
|
|
769
812
|
*/
|
|
770
813
|
async getOrganizations() {
|
|
771
814
|
try {
|
|
772
|
-
const data = await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, 'organizations', this.#reqOptions));
|
|
815
|
+
const data = await this.#executeWithRetry(async () => await (0, http_client_1.getResponseJson)(await (0, http_client_1.createGetRequest)(this.#baseUrl, 'organizations', this.#reqOptions)));
|
|
773
816
|
return this.#handleApiSuccess(data);
|
|
774
817
|
}
|
|
775
818
|
catch (e) {
|
|
@@ -1182,7 +1225,11 @@ class SocketSdk {
|
|
|
1182
1225
|
*
|
|
1183
1226
|
* @throws {Error} When server returns 5xx status codes
|
|
1184
1227
|
*/
|
|
1185
|
-
async streamOrgFullScan(orgSlug, fullScanId,
|
|
1228
|
+
async streamOrgFullScan(orgSlug, fullScanId, options) {
|
|
1229
|
+
const { output } = {
|
|
1230
|
+
__proto__: null,
|
|
1231
|
+
...options,
|
|
1232
|
+
};
|
|
1186
1233
|
try {
|
|
1187
1234
|
const req = (0, http_client_1.getHttpModule)(this.#baseUrl)
|
|
1188
1235
|
.request(`${this.#baseUrl}orgs/${encodeURIComponent(orgSlug)}/full-scans/${encodeURIComponent(fullScanId)}`, {
|
|
@@ -1196,12 +1243,23 @@ class SocketSdk {
|
|
|
1196
1243
|
throw new http_client_1.ResponseError(res);
|
|
1197
1244
|
}
|
|
1198
1245
|
if (typeof output === 'string') {
|
|
1199
|
-
// Stream to file
|
|
1200
|
-
|
|
1246
|
+
// Stream to file with error handling.
|
|
1247
|
+
const writeStream = (0, node_fs_1.createWriteStream)(output);
|
|
1248
|
+
res.pipe(writeStream);
|
|
1249
|
+
/* c8 ignore next 4 - Write stream error handler, difficult to test reliably */
|
|
1250
|
+
writeStream.on('error', error => {
|
|
1251
|
+
throw new Error(`Failed to write to file: ${output}`, {
|
|
1252
|
+
cause: error,
|
|
1253
|
+
});
|
|
1254
|
+
});
|
|
1201
1255
|
}
|
|
1202
1256
|
else if (output === true) {
|
|
1203
|
-
// Stream to stdout
|
|
1257
|
+
// Stream to stdout with error handling.
|
|
1204
1258
|
res.pipe(process.stdout);
|
|
1259
|
+
/* c8 ignore next 3 - Stdout error handler, difficult to test reliably */
|
|
1260
|
+
process.stdout.on('error', error => {
|
|
1261
|
+
throw new Error('Failed to write to stdout', { cause: error });
|
|
1262
|
+
});
|
|
1205
1263
|
}
|
|
1206
1264
|
// If output is false or undefined, just return the response without streaming
|
|
1207
1265
|
return this.#handleApiSuccess(res);
|
|
@@ -1240,8 +1298,8 @@ class SocketSdk {
|
|
|
1240
1298
|
controller.enqueue(data);
|
|
1241
1299
|
}
|
|
1242
1300
|
catch (e) {
|
|
1243
|
-
//
|
|
1244
|
-
|
|
1301
|
+
// Log parse errors for debugging invalid NDJSON lines.
|
|
1302
|
+
(0, debug_1.debugLog)('streamPatchesFromScan', `Failed to parse line: ${e}`);
|
|
1245
1303
|
}
|
|
1246
1304
|
}
|
|
1247
1305
|
});
|
|
@@ -1334,7 +1392,11 @@ class SocketSdk {
|
|
|
1334
1392
|
*
|
|
1335
1393
|
* @throws {Error} When server returns 5xx status codes
|
|
1336
1394
|
*/
|
|
1337
|
-
async uploadManifestFiles(orgSlug, filepaths,
|
|
1395
|
+
async uploadManifestFiles(orgSlug, filepaths, options) {
|
|
1396
|
+
const { pathsRelativeTo = '.' } = {
|
|
1397
|
+
__proto__: null,
|
|
1398
|
+
...options,
|
|
1399
|
+
};
|
|
1338
1400
|
const basePath = (0, utils_1.resolveBasePath)(pathsRelativeTo);
|
|
1339
1401
|
const absFilepaths = (0, utils_1.resolveAbsPaths)(filepaths, basePath);
|
|
1340
1402
|
try {
|
package/dist/types.d.ts
CHANGED
|
@@ -73,12 +73,14 @@ export type GotOptions = {
|
|
|
73
73
|
http?: HttpAgent | undefined;
|
|
74
74
|
https?: HttpsAgent | undefined;
|
|
75
75
|
};
|
|
76
|
-
export type QueryParams = Record<string,
|
|
76
|
+
export type QueryParams = Record<string, unknown>;
|
|
77
77
|
export type HeadersRecord = Record<string, string | string[]> | undefined;
|
|
78
|
+
export type SocketMetricSchema = components['schemas']['SocketMetricSchema'];
|
|
79
|
+
export type SocketId = components['schemas']['SocketId'];
|
|
78
80
|
export type SocketArtifactWithExtras = SocketArtifact & {
|
|
79
|
-
scorecards?:
|
|
80
|
-
supplyChainRisk?:
|
|
81
|
-
topLevelAncestors?:
|
|
81
|
+
scorecards?: unknown | undefined;
|
|
82
|
+
supplyChainRisk?: SocketMetricSchema | undefined;
|
|
83
|
+
topLevelAncestors?: SocketId[] | undefined;
|
|
82
84
|
};
|
|
83
85
|
export type RequestOptions = ((HttpsRequestOptions & {
|
|
84
86
|
headers?: HeadersRecord | undefined;
|
|
@@ -130,6 +132,8 @@ export type SocketSdkGenericResult<T> = {
|
|
|
130
132
|
export interface SocketSdkOptions {
|
|
131
133
|
agent?: Agent | GotOptions | undefined;
|
|
132
134
|
baseUrl?: string | undefined;
|
|
135
|
+
retries?: number | undefined;
|
|
136
|
+
retryDelay?: number | undefined;
|
|
133
137
|
timeout?: number | undefined;
|
|
134
138
|
userAgent?: string | undefined;
|
|
135
139
|
}
|
|
@@ -157,3 +161,21 @@ export type BatchPackageStreamOptions = {
|
|
|
157
161
|
concurrencyLimit?: number | undefined;
|
|
158
162
|
queryParams?: QueryParams | undefined;
|
|
159
163
|
};
|
|
164
|
+
export type CreateDependenciesSnapshotOptions = {
|
|
165
|
+
pathsRelativeTo?: string | undefined;
|
|
166
|
+
queryParams?: QueryParams | undefined;
|
|
167
|
+
};
|
|
168
|
+
export type CreateOrgFullScanOptions = {
|
|
169
|
+
pathsRelativeTo?: string | undefined;
|
|
170
|
+
queryParams?: QueryParams | undefined;
|
|
171
|
+
};
|
|
172
|
+
export type CreateScanFromFilepathsOptions = {
|
|
173
|
+
issueRules?: Record<string, boolean> | undefined;
|
|
174
|
+
pathsRelativeTo?: string | undefined;
|
|
175
|
+
};
|
|
176
|
+
export type StreamOrgFullScanOptions = {
|
|
177
|
+
output?: boolean | string | undefined;
|
|
178
|
+
};
|
|
179
|
+
export type UploadManifestFilesOptions = {
|
|
180
|
+
pathsRelativeTo?: string | undefined;
|
|
181
|
+
};
|
package/dist/utils.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare function promiseWithResolvers<T>(): ReturnType<typeof Promise.wit
|
|
|
14
14
|
* Convert query parameters to URLSearchParams with API-compatible key normalization.
|
|
15
15
|
* Transforms camelCase keys to snake_case and filters out empty values.
|
|
16
16
|
*/
|
|
17
|
-
export declare function queryToSearchParams(init?: URLSearchParams | string | QueryParams | Iterable<[string,
|
|
17
|
+
export declare function queryToSearchParams(init?: URLSearchParams | string | QueryParams | Iterable<[string, unknown]> | ReadonlyArray<[string, unknown]> | null | undefined): URLSearchParams;
|
|
18
18
|
/**
|
|
19
19
|
* Convert relative file paths to absolute paths.
|
|
20
20
|
* Resolves paths relative to specified base directory or current working directory.
|
package/dist/utils.js
CHANGED
|
@@ -47,8 +47,8 @@ function promiseWithResolvers() {
|
|
|
47
47
|
* Transforms camelCase keys to snake_case and filters out empty values.
|
|
48
48
|
*/
|
|
49
49
|
function queryToSearchParams(init) {
|
|
50
|
-
const params = new URLSearchParams(init
|
|
51
|
-
const normalized =
|
|
50
|
+
const params = new URLSearchParams(init);
|
|
51
|
+
const normalized = Object.create(null);
|
|
52
52
|
const entries = params.entries();
|
|
53
53
|
for (const entry of entries) {
|
|
54
54
|
let key = entry[0];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@socketsecurity/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "SDK for the Socket API client",
|
|
6
6
|
"author": {
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"update:socket": "pnpm -r update '@socketsecurity/*' --latest"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@socketsecurity/registry": "1.
|
|
78
|
+
"@socketsecurity/registry": "1.4.0"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@biomejs/biome": "2.2.4",
|