Skip to content

Commit 93ed212

Browse files
authored
feat: initial implementation; trim CDX SBOM, convert CDX XML to JSON, convert SPDX to CDX (#1)
1 parent 5c87273 commit 93ed212

37 files changed

+442327
-0
lines changed

.github/workflows/release.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: read
13+
id-token: write
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Setup Node.js
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version-file: '.nvmrc'
22+
registry-url: 'https://registry.npmjs.org'
23+
24+
- name: Install dependencies and build
25+
run: |
26+
npm ci
27+
npm run build
28+
29+
- name: Publish to NPM
30+
run: npm publish --provenance --access public
31+
env:
32+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.github/workflows/validate.yml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Validate
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
jobs:
8+
lint:
9+
name: Lint
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: actions/setup-node@v4
14+
with:
15+
node-version: '24'
16+
cache: 'npm'
17+
18+
- run: npm ci
19+
- run: npm run lint
20+
21+
build:
22+
name: Build (Node ${{ matrix.node-version }})
23+
runs-on: ubuntu-latest
24+
strategy:
25+
matrix:
26+
node-version: [22, 24]
27+
steps:
28+
- uses: actions/checkout@v4
29+
- uses: actions/setup-node@v4
30+
with:
31+
node-version: ${{ matrix.node-version }}
32+
cache: 'npm'
33+
34+
- run: npm ci
35+
- run: npm run build
36+
37+
test:
38+
name: Test (Node ${{ matrix.node-version }})
39+
runs-on: ubuntu-latest
40+
strategy:
41+
matrix:
42+
node-version: [22, 24]
43+
steps:
44+
- uses: actions/checkout@v4
45+
- uses: actions/setup-node@v4
46+
with:
47+
node-version: ${{ matrix.node-version }}
48+
cache: 'npm'
49+
50+
- run: npm ci
51+
- run: npm run test
52+
53+
format:
54+
name: Format
55+
runs-on: ubuntu-latest
56+
steps:
57+
- uses: actions/checkout@v4
58+
- uses: actions/setup-node@v4
59+
with:
60+
node-version: '24'
61+
cache: 'npm'
62+
63+
- run: npm ci
64+
- run: npm run format:check

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1+
.claude
2+
.gemini
3+
.kiro
4+
5+
dist
16
node_modules

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
24

.oxlintrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"plugins": ["typescript", "unicorn", "oxc", "node", "promise"]
3+
}

.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fixtures/**/*
2+
schemas/**/*
3+
src/types/bom/**/*

.prettierrc.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"singleQuote": true,
3+
"objectWrap": "collapse",
4+
"overrides": [{ "files": "*.json", "options": { "objectWrap": "preserve" } }]
5+
}

CONTRIBUTING

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
## Development
2+
3+
### Building
4+
5+
```bash
6+
npm run build
7+
```
8+
9+
### Testing
10+
11+
```bash
12+
npm test
13+
```
14+
15+
### Linting
16+
17+
```bash
18+
npm run lint
19+
npm run lint:fix
20+
```
21+
22+
### Formatting
23+
24+
```bash
25+
npm run format:check
26+
npm run format:write
27+
```

LICENSE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright (c) 2025 HeroDevs, Inc
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4+
5+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# @herodevs/eol-shared
2+
3+
A TypeScript utility library for End-of-Life (EOL) scanning and analysis.
4+
5+
## Installation
6+
7+
```bash
8+
npm install @herodevs/eol-shared
9+
```
10+
11+
## Requirements
12+
13+
- Node.js 22 or higher
14+
15+
## API
16+
17+
### [`spdxToCdxBom(spdxBom: SPDX23): CdxBom`](./src/spdx-to-cdx.mts#L61)
18+
19+
Converts an SPDX BOM to CycloneDX format. This conversion takes the most important package and relationship data from SPDX and translates them into CycloneDX components and dependencies as closely as possible.
20+
21+
```typescript
22+
import { spdxToCdxBom } from '@herodevs/eol-shared';
23+
import type { CdxBom } from '@herodevs/eol-shared';
24+
25+
const spdxBom = {
26+
/* your SPDX BOM data */
27+
};
28+
const cdxBom: CdxBom = spdxToCdxBom(spdxBom);
29+
```
30+
31+
**Parameters**: `spdxBom` - The SPDX BOM object to convert
32+
**Returns**: A CycloneDX BOM object
33+
34+
### [`xmlStringToJSON(xmlString: string): CdxBom`](./src/cdx-xml-to-json.mts#L161)
35+
36+
Converts a CycloneDX XML string to a JSON object. The CycloneDX spec does not change between formats, so conversion from XML to JSON is lossless.
37+
38+
```typescript
39+
import { xmlStringToJSON } from '@herodevs/eol-shared';
40+
import type { CdxBom } from '@herodevs/eol-shared';
41+
42+
const xmlString = `<?xml version="1.0"?>...`;
43+
const jsonBom: CdxBom = xmlStringToJSON(xmlString);
44+
```
45+
46+
**Parameters**: `xmlString` - The XML string to parse
47+
**Returns**: The parsed CycloneDX BOM object
48+
49+
### [`trimCdxBom(cdxBom: CdxBom): CdxBom`](./src/trim-cdx-bom.mts#L3)
50+
51+
Creates a trimmed copy of a CycloneDX BOM by removing SBOM data not necessary for EOL scanning:
52+
53+
- `externalReferences` from components
54+
- `evidence` from components
55+
- `hashes` from components
56+
- `properties` from components
57+
58+
```typescript
59+
import { trimCdxBom } from '@herodevs/eol-shared';
60+
import type { CdxBom } from '@herodevs/eol-shared';
61+
62+
const originalBom: CdxBom = {
63+
/* your CycloneDX BOM */
64+
};
65+
const trimmedBom: CdxBom = trimCdxBom(originalBom);
66+
```
67+
68+
**Parameters**: `cdxBom` - The CycloneDX BOM to trim
69+
**Returns**: A new trimmed CycloneDX BOM object
70+
71+
### Types
72+
73+
The package exports the following TypeScript types:
74+
75+
- `CdxBom` - CycloneDX BOM structure as exported from [`@cyclonedx/cyclonedx-library`](https://github.com/CycloneDX/cyclonedx-javascript-library/blob/447db28f47ffd03b6f9c2f4a450bef0f0392c6bb/src/serialize/json/types.ts#L76)
76+
- `Component` - Component definition
77+
- `Dependency` - Dependency relationship
78+
- `Hash` - Hash/checksum information
79+
- `License` - License information
80+
- `ExternalReference` - External reference data
81+
- `ComponentScope` - Component scope enumeration
82+
83+
## Resources
84+
85+
This package is designed to work with:
86+
87+
- [CycloneDX](https://cyclonedx.org/) - Industry standard for Software Bill of Materials
88+
- [SPDX](https://spdx.dev/) - Software Package Data Exchange standard

0 commit comments

Comments
 (0)