blackduck-api-client
v1.0.1
Published
TypeScript client for the Black Duck REST API
Maintainers
Readme
Black Duck API Client
A zero-dependency TypeScript client for the Black Duck REST API (Software Composition Analysis).
Features
- Full TypeScript — every request and response is fully typed
- Read-only — covers all major GET endpoints for projects, BOM components, vulnerabilities, licenses, users, code locations, and policy rules
- Chainable resources —
client.project('id').version('id').components()pattern - Dual package — ships CJS + ESM, works in Node.js and browsers
- Zero runtime dependencies — uses native
fetchandURLSearchParams - Request events — hook into every HTTP request for logging and monitoring
- Semantic versioning — automated releases via Conventional Commits
Installation
npm install blackduck-api-clientQuick Start
import { BlackDuckClient } from 'blackduck-api-client';
const client = new BlackDuckClient({
apiUrl: 'https://blackduck.example.com',
token: 'my-personal-access-token',
});
// List projects
const page = await client.projects({ limit: 10 });
console.log(page.totalCount, 'projects found');
// Get BOM components for a project version
const bom = await client.project('proj-uuid').version('ver-uuid').components();
for (const comp of bom.items) {
console.log(comp.componentName, comp.policyStatus);
}
// Get vulnerable components only
const vulns = await client.project('proj-uuid').version('ver-uuid').vulnerableComponents();
const critical = vulns.items.filter(v =>
v.vulnerabilityWithRemediation.severity === 'CRITICAL'
);
// Get the risk profile
const risk = await client.project('proj-uuid').version('ver-uuid').riskProfile();
console.log('High vulns:', risk.categories.VULNERABILITY?.HIGH);
// Search the Knowledge Base for a component
const results = await client.components({ q: 'log4j', limit: 5 });
// Get the current user
const me = await client.currentUser();
console.log(me.userName);Authentication
The client uses API Token authentication (recommended for integrations):
const client = new BlackDuckClient({
apiUrl: 'https://blackduck.example.com',
token: 'my-personal-access-token',
// Optional — defaults shown:
apiPath: 'api',
});To generate a personal access token, go to Black Duck → User menu → My Access Tokens.
The Authorization: token <api-token> header is sent automatically with every request.
API Reference
BlackDuckClient
The main client. All methods return Promises.
Projects
// List projects (paginated)
await client.projects({ q: 'name:my-app', limit: 25, offset: 0 });
// Get a single project (await directly or call .get())
const project = await client.project('proj-uuid');
const project = await client.project('proj-uuid').get();
// List project versions
await client.project('proj-uuid').versions({ limit: 10 });
// Navigate to a project version (await directly or chain)
const version = await client.project('proj-uuid').version('ver-uuid');Project Versions (BOM, Risk, Policy)
// Bill of Materials — all components
await client.project('proj-uuid').version('ver-uuid').components({ limit: 100 });
// Vulnerable components only
await client.project('proj-uuid').version('ver-uuid').vulnerableComponents();
// Aggregated risk profile (VULNERABILITY, LICENSE, OPERATIONAL, ACTIVITY, VERSION)
await client.project('proj-uuid').version('ver-uuid').riskProfile();
// Overall policy status
await client.project('proj-uuid').version('ver-uuid').policyStatus();Knowledge Base — Components
// Search KB components
await client.components({ q: 'log4j', limit: 10 });
// Get a component (await directly or chain)
const comp = await client.component('comp-uuid');
// List component versions
await client.component('comp-uuid').versions({ q: 'versionName:2.17' });
// Get a specific component version
await client.component('comp-uuid').version('ver-uuid');Vulnerabilities
// List vulnerabilities
await client.vulnerabilities({ q: 'severity:CRITICAL', limit: 50 });
// Get a single vulnerability by CVE or BDSA ID
await client.vulnerability('CVE-2021-44228');
await client.vulnerability('BDSA-2021-3544');Licenses
// List licenses
await client.licenses({ q: 'name:Apache', limit: 20 });
// Get a single license
await client.license('lic-uuid');Users
// List users
await client.users({ q: 'userName:jdoe', limit: 10 });
// Get a single user by UUID
await client.user('user-uuid');
// Get the currently authenticated user
await client.currentUser();Roles
// List all roles
await client.roles();Notifications
// List notifications
await client.notifications({
filter: 'notificationType:VULNERABILITY',
startDate: '2024-01-01T00:00:00.000Z',
endDate: '2024-12-31T23:59:59.999Z',
});Code Locations (Scans)
// List code locations
await client.codeLocations({ q: 'name:my-repo', limit: 20 });
// Get a code location (await directly or chain)
const location = await client.codeLocation('loc-uuid');
// Get scan summaries for a code location
await client.codeLocation('loc-uuid').scanSummaries();Policy Rules
// List policy rules
await client.policyRules({ limit: 50 });
// Get a single policy rule
await client.policyRule('rule-uuid');Pagination
All list endpoints return a paged response:
interface BlackDuckPagedResponse<T> {
totalCount: number;
items: T[];
_meta: BlackDuckMeta;
}To iterate through all pages:
let offset = 0;
const limit = 100;
const allComponents: BlackDuckBomComponent[] = [];
while (true) {
const page = await client
.project('proj-uuid')
.version('ver-uuid')
.components({ offset, limit });
allComponents.push(...page.items);
if (allComponents.length >= page.totalCount) break;
offset += limit;
}Request Events
Subscribe to every HTTP request for logging, metrics, or debugging:
client.on('request', (event) => {
console.log(`[${event.method}] ${event.url} — ${event.durationMs}ms (${event.statusCode})`);
if (event.error) {
console.error('Request failed:', event.error.message);
}
});Event payload:
| Field | Type | Description |
|-------|------|-------------|
| url | string | Full URL requested |
| method | 'GET' | HTTP method |
| startedAt | Date | Request start timestamp |
| finishedAt | Date | Request end timestamp |
| durationMs | number | Duration in milliseconds |
| statusCode | number? | HTTP status code |
| error | Error? | Error object if the request failed |
Error Handling
import { BlackDuckApiError } from 'blackduck-api-client';
try {
await client.project('nonexistent-uuid');
} catch (err) {
if (err instanceof BlackDuckApiError) {
console.log(err.status); // 404
console.log(err.statusText); // 'Not Found'
console.log(err.message); // 'Black Duck API error: 404 Not Found'
}
}TypeScript Types
All domain types are exported:
import type {
BlackDuckProject,
BlackDuckProjectVersion,
BlackDuckBomComponent,
BlackDuckVulnerableBomComponent,
BlackDuckVulnerabilityWithRemediation,
BlackDuckRiskProfile,
BlackDuckRiskCounts,
BlackDuckPolicyStatus,
BlackDuckComponent,
BlackDuckComponentVersion,
BlackDuckVulnerability,
BlackDuckCvss2,
BlackDuckCvss3,
BlackDuckLicense,
BlackDuckUser,
BlackDuckRole,
BlackDuckNotification,
BlackDuckCodeLocation,
BlackDuckScanSummary,
BlackDuckPolicyRule,
BlackDuckPagedResponse,
BlackDuckMeta,
// ... and many more
} from 'blackduck-api-client';Contributing
See CONTRIBUTING.md for development guidelines.
