@herodevs/cli 2.0.0-beta.0 → 2.0.0-beta.10
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/README.md +187 -109
- package/bin/dev.js +1 -4
- package/bin/main.js +3 -3
- package/bin/run.js +1 -1
- package/dist/api/gql-operations.d.ts +2 -0
- package/dist/api/gql-operations.js +36 -0
- package/dist/api/nes.client.d.ts +12 -0
- package/dist/api/nes.client.js +75 -0
- package/dist/commands/scan/eol.d.ts +13 -19
- package/dist/commands/scan/eol.js +163 -149
- package/dist/config/constants.d.ts +9 -2
- package/dist/config/constants.js +19 -2
- package/dist/hooks/finally/finally.d.ts +3 -0
- package/dist/hooks/finally/finally.js +18 -0
- package/dist/hooks/{npm-update-notifier.js → init/00_npm-update-notifier.js} +3 -3
- package/dist/hooks/init/01_initialize_amplitude.d.ts +3 -0
- package/dist/hooks/init/01_initialize_amplitude.js +15 -0
- package/dist/service/analytics.svc.d.ts +28 -0
- package/dist/service/analytics.svc.js +112 -0
- package/dist/service/{eol/cdx.svc.d.ts → cdx.svc.d.ts} +8 -16
- package/dist/service/{eol/cdx.svc.js → cdx.svc.js} +17 -7
- package/dist/service/display.svc.d.ts +22 -0
- package/dist/service/display.svc.js +72 -0
- package/dist/service/file.svc.d.ts +20 -0
- package/dist/service/file.svc.js +71 -0
- package/dist/service/log.svc.d.ts +1 -0
- package/dist/service/log.svc.js +9 -0
- package/dist/service/{eol/sbom.worker.js → sbom.worker.js} +2 -1
- package/dist/utils/strip-typename.d.ts +1 -0
- package/dist/utils/strip-typename.js +15 -0
- package/package.json +33 -22
- package/dist/api/client.d.ts +0 -12
- package/dist/api/client.js +0 -43
- package/dist/api/nes/nes.client.d.ts +0 -23
- package/dist/api/nes/nes.client.js +0 -107
- package/dist/api/queries/nes/sbom.d.ts +0 -3
- package/dist/api/queries/nes/sbom.js +0 -35
- package/dist/api/queries/nes/telemetry.d.ts +0 -2
- package/dist/api/queries/nes/telemetry.js +0 -24
- package/dist/api/types/hd-cli.types.d.ts +0 -30
- package/dist/api/types/hd-cli.types.js +0 -10
- package/dist/api/types/nes.types.d.ts +0 -53
- package/dist/api/types/nes.types.js +0 -1
- package/dist/commands/report/committers.d.ts +0 -23
- package/dist/commands/report/committers.js +0 -146
- package/dist/commands/report/purls.d.ts +0 -15
- package/dist/commands/report/purls.js +0 -84
- package/dist/commands/scan/sbom.d.ts +0 -21
- package/dist/commands/scan/sbom.js +0 -159
- package/dist/service/committers.svc.d.ts +0 -70
- package/dist/service/committers.svc.js +0 -196
- package/dist/service/eol/eol.svc.d.ts +0 -14
- package/dist/service/eol/eol.svc.js +0 -49
- package/dist/service/error.svc.d.ts +0 -8
- package/dist/service/error.svc.js +0 -28
- package/dist/service/nes/nes.svc.d.ts +0 -5
- package/dist/service/nes/nes.svc.js +0 -27
- package/dist/service/purls.svc.d.ts +0 -23
- package/dist/service/purls.svc.js +0 -99
- package/dist/ui/date.ui.d.ts +0 -1
- package/dist/ui/date.ui.js +0 -15
- package/dist/ui/eol.ui.d.ts +0 -15
- package/dist/ui/eol.ui.js +0 -113
- package/dist/ui/shared.ui.d.ts +0 -6
- package/dist/ui/shared.ui.js +0 -16
- /package/dist/hooks/{npm-update-notifier.d.ts → init/00_npm-update-notifier.d.ts} +0 -0
- /package/dist/hooks/{prerun.d.ts → prerun/prerun.d.ts} +0 -0
- /package/dist/hooks/{prerun.js → prerun/prerun.js} +0 -0
- /package/dist/service/{eol/sbom.worker.d.ts → sbom.worker.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -10,27 +10,68 @@ The HeroDevs CLI
|
|
|
10
10
|
* [@herodevs/cli](#herodevscli)
|
|
11
11
|
<!-- tocstop -->
|
|
12
12
|
|
|
13
|
+
### Prerequisites
|
|
14
|
+
|
|
15
|
+
- Install node v20 or higher: [Download Node](https://nodejs.org/en/download)
|
|
16
|
+
- The HeroDevs CLI expects that you have all required technology installed for the project that you are running the CLI against
|
|
17
|
+
- For example, if you are running the CLI against a Gradle project, the CLI expects you to have Java installed.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Installation methods
|
|
21
|
+
|
|
22
|
+
#### Node Package Execute (NPX)
|
|
23
|
+
|
|
24
|
+
With Node installed, you can run the CLI directly from the npm registry without installing it globally or locally on your system
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
npx @herodevs/cli@beta
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Global NPM Installation
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
npm install -g @herodevs/cli@beta
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### Binary Installation
|
|
37
|
+
|
|
38
|
+
HeroDevs CLI is available as a binary installation, without requiring `npm`. To do that, you may either download and run the script manually, or use the following cURL or Wget command:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
curl -o- https://raw.githubusercontent.com/herodevs/cli/v2.0.0-beta.10/scripts/install.sh | bash
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
wget -qO- https://raw.githubusercontent.com/herodevs/cli/v2.0.0-beta.10/scripts/install.sh | bash
|
|
46
|
+
```
|
|
47
|
+
|
|
13
48
|
## TERMS
|
|
14
49
|
|
|
15
50
|
Use of this CLI is governed by the [HeroDevs End of Life Dataset Terms of Service and Data Policy](https://docs.herodevs.com/legal/end-of-life-dataset-terms).
|
|
16
51
|
|
|
17
52
|
## Scanning Behavior
|
|
18
53
|
|
|
19
|
-
The CLI
|
|
54
|
+
The CLI is designed to be non-invasive:
|
|
55
|
+
|
|
56
|
+
* It does **not** install dependencies or modify package manager files (package-lock.json, yarn.lock, etc.)
|
|
57
|
+
* It analyzes the project in its current state
|
|
20
58
|
|
|
21
|
-
|
|
22
|
-
* They analyze the project in its current state
|
|
23
|
-
* If you need dependencies installed for accurate scanning, please install them manually before running the scan
|
|
59
|
+
## Installing Dependencies Before Use
|
|
24
60
|
|
|
61
|
+
Some projects and ecosystems require projects to have dependencies installed already, to achieve an accurate scan result. It is **highly** recommended that you install all dependencies of your project to your working directory, before running a scan on your project, to ensure scan accuracy.
|
|
62
|
+
|
|
63
|
+
### Java Users
|
|
64
|
+
|
|
65
|
+
Maven and Gradle projects should run an install and build before scanning
|
|
25
66
|
|
|
26
67
|
## Usage
|
|
27
68
|
<!-- usage -->
|
|
28
69
|
```sh-session
|
|
29
|
-
$ npm install -g @herodevs/cli
|
|
70
|
+
$ npm install -g @herodevs/cli@beta
|
|
30
71
|
$ hd COMMAND
|
|
31
72
|
running command...
|
|
32
73
|
$ hd (--version)
|
|
33
|
-
@herodevs/cli/2.0.0-beta.
|
|
74
|
+
@herodevs/cli/2.0.0-beta.10 darwin-arm64 node-v22.18.0
|
|
34
75
|
$ hd --help [COMMAND]
|
|
35
76
|
USAGE
|
|
36
77
|
$ hd COMMAND
|
|
@@ -40,11 +81,9 @@ USAGE
|
|
|
40
81
|
## Commands
|
|
41
82
|
<!-- commands -->
|
|
42
83
|
* [`hd help [COMMAND]`](#hd-help-command)
|
|
43
|
-
* [`hd report committers`](#hd-report-committers)
|
|
44
|
-
* [`hd report purls`](#hd-report-purls)
|
|
45
84
|
* [`hd scan eol`](#hd-scan-eol)
|
|
46
|
-
* [`hd scan sbom`](#hd-scan-sbom)
|
|
47
85
|
* [`hd update [CHANNEL]`](#hd-update-channel)
|
|
86
|
+
* **NOTE:** Only applies to [binary installation method](#binary-installation). NPM users should use [`npm install`](#global-npm-installation) to update to the latest version.
|
|
48
87
|
|
|
49
88
|
## `hd help [COMMAND]`
|
|
50
89
|
|
|
@@ -64,170 +103,209 @@ DESCRIPTION
|
|
|
64
103
|
Display help for hd.
|
|
65
104
|
```
|
|
66
105
|
|
|
67
|
-
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.
|
|
106
|
+
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.32/src/commands/help.ts)_
|
|
68
107
|
|
|
69
|
-
## `hd
|
|
108
|
+
## `hd scan eol`
|
|
70
109
|
|
|
71
|
-
|
|
110
|
+
Scan a given SBOM for EOL data
|
|
72
111
|
|
|
73
112
|
```
|
|
74
113
|
USAGE
|
|
75
|
-
$ hd
|
|
114
|
+
$ hd scan eol [--json] [-f <value> | -d <value>] [-s] [--saveSbom] [--version]
|
|
76
115
|
|
|
77
116
|
FLAGS
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
-s, --save
|
|
117
|
+
-d, --dir=<value> [default: <current directory>] The directory to scan in order to create a cyclonedx SBOM
|
|
118
|
+
-f, --file=<value> The file path of an existing cyclonedx SBOM to scan for EOL
|
|
119
|
+
-s, --save Save the generated report as herodevs.report.json in the scanned directory
|
|
120
|
+
--saveSbom Save the generated SBOM as herodevs.sbom.json in the scanned directory
|
|
121
|
+
--version Show CLI version.
|
|
81
122
|
|
|
82
123
|
GLOBAL FLAGS
|
|
83
124
|
--json Format output as json.
|
|
84
125
|
|
|
85
126
|
DESCRIPTION
|
|
86
|
-
|
|
127
|
+
Scan a given SBOM for EOL data
|
|
87
128
|
|
|
88
129
|
EXAMPLES
|
|
89
|
-
|
|
130
|
+
Default behavior (no command or flags specified)
|
|
131
|
+
|
|
132
|
+
$ hd
|
|
133
|
+
|
|
134
|
+
Equivalent to
|
|
135
|
+
|
|
136
|
+
$ hd scan eol --dir .
|
|
90
137
|
|
|
91
|
-
|
|
138
|
+
Skip SBOM generation and specify an existing file
|
|
92
139
|
|
|
93
|
-
|
|
140
|
+
$ hd scan eol --file /path/to/sbom.json
|
|
94
141
|
|
|
95
|
-
|
|
142
|
+
Save the report or SBOM to a file
|
|
143
|
+
|
|
144
|
+
$ hd scan eol --save --saveSbom
|
|
145
|
+
|
|
146
|
+
Output the report in JSON format (for APIs, CI, etc.)
|
|
147
|
+
|
|
148
|
+
$ hd scan eol --json
|
|
96
149
|
```
|
|
97
150
|
|
|
98
|
-
_See code: [src/commands/
|
|
151
|
+
_See code: [src/commands/scan/eol.ts](https://github.com/herodevs/cli/blob/v2.0.0-beta.10/src/commands/scan/eol.ts)_
|
|
99
152
|
|
|
100
|
-
## `hd
|
|
153
|
+
## `hd update [CHANNEL]`
|
|
154
|
+
|
|
155
|
+
update the hd CLI
|
|
101
156
|
|
|
102
|
-
|
|
157
|
+
* **NOTE:** Only applies to [binary installation method](#binary-installation). NPM users should use [`npm install`](#global-npm-installation) to update to the latest version.
|
|
103
158
|
|
|
104
159
|
```
|
|
105
160
|
USAGE
|
|
106
|
-
$ hd
|
|
161
|
+
$ hd update [CHANNEL] [--force | | [-a | -v <value> | -i]] [-b ]
|
|
107
162
|
|
|
108
163
|
FLAGS
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
|
|
114
|
-
GLOBAL FLAGS
|
|
115
|
-
--json Format output as json.
|
|
164
|
+
-a, --available See available versions.
|
|
165
|
+
-b, --verbose Show more details about the available versions.
|
|
166
|
+
-i, --interactive Interactively select version to install. This is ignored if a channel is provided.
|
|
167
|
+
-v, --version=<value> Install a specific version.
|
|
168
|
+
--force Force a re-download of the requested version.
|
|
116
169
|
|
|
117
170
|
DESCRIPTION
|
|
118
|
-
|
|
171
|
+
update the hd CLI
|
|
119
172
|
|
|
120
173
|
EXAMPLES
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
$ hd report purls --dir=./my-project
|
|
174
|
+
Update to the stable channel:
|
|
124
175
|
|
|
125
|
-
|
|
176
|
+
$ hd update stable
|
|
126
177
|
|
|
127
|
-
|
|
178
|
+
Update to a specific version:
|
|
128
179
|
|
|
129
|
-
|
|
130
|
-
```
|
|
180
|
+
$ hd update --version 1.0.0
|
|
131
181
|
|
|
132
|
-
|
|
182
|
+
Interactively select version:
|
|
133
183
|
|
|
134
|
-
|
|
184
|
+
$ hd update --interactive
|
|
135
185
|
|
|
136
|
-
|
|
186
|
+
See available versions:
|
|
137
187
|
|
|
188
|
+
$ hd update --available
|
|
138
189
|
```
|
|
139
|
-
USAGE
|
|
140
|
-
$ hd scan eol [--json] [-f <value>] [-p <value>] [-d <value>] [-s] [-a] [-t]
|
|
141
|
-
|
|
142
|
-
FLAGS
|
|
143
|
-
-a, --all Show all components (default is EOL and SUPPORTED only)
|
|
144
|
-
-d, --dir=<value> The directory to scan in order to create a cyclonedx sbom
|
|
145
|
-
-f, --file=<value> The file path of an existing cyclonedx sbom to scan for EOL
|
|
146
|
-
-p, --purls=<value> The file path of a list of purls to scan for EOL
|
|
147
|
-
-s, --save Save the generated report as eol.report.json in the scanned directory
|
|
148
|
-
-t, --table Display the results in a table
|
|
149
190
|
|
|
150
|
-
|
|
151
|
-
|
|
191
|
+
_See code: [@oclif/plugin-update](https://github.com/oclif/plugin-update/blob/v4.7.4/src/commands/update.ts)_
|
|
192
|
+
<!-- commandsstop -->
|
|
152
193
|
|
|
153
|
-
|
|
154
|
-
Scan a given sbom for EOL data
|
|
194
|
+
## CI/CD Usage
|
|
155
195
|
|
|
156
|
-
|
|
157
|
-
$ hd scan eol --dir=./my-project
|
|
196
|
+
You can use `@herodevs/cli` in your CI/CD pipelines to automate EOL scanning.
|
|
158
197
|
|
|
159
|
-
|
|
198
|
+
### Using the Docker Image (Recommended)
|
|
160
199
|
|
|
161
|
-
|
|
200
|
+
We provide a Docker image that's pre-configured to run EOL scans. Based on [`cdxgen`](https://github.com/CycloneDX/cdxgen),
|
|
201
|
+
it contains build tools for most project types and will provide best results when generating an SBOM. Use these templates to generate a report and save it to your CI job artifact for analysis and processing after your scan runs.
|
|
162
202
|
|
|
163
|
-
|
|
164
|
-
```
|
|
203
|
+
#### GitHub Actions
|
|
165
204
|
|
|
166
|
-
|
|
205
|
+
```yaml
|
|
206
|
+
## .github/workflows/herodevs-eol-scan.yml
|
|
207
|
+
name: HeroDevs EOL Scan
|
|
167
208
|
|
|
168
|
-
|
|
209
|
+
on:
|
|
210
|
+
push:
|
|
211
|
+
branches: [ main ]
|
|
212
|
+
pull_request:
|
|
213
|
+
branches: [ main ]
|
|
169
214
|
|
|
170
|
-
|
|
215
|
+
jobs:
|
|
216
|
+
scan:
|
|
217
|
+
runs-on: ubuntu-latest
|
|
218
|
+
steps:
|
|
219
|
+
- uses: actions/checkout@v4
|
|
171
220
|
|
|
221
|
+
- name: Run EOL Scan with Docker
|
|
222
|
+
uses: docker://ghcr.io/herodevs/eol-scan
|
|
223
|
+
with:
|
|
224
|
+
args: "-s"
|
|
225
|
+
|
|
226
|
+
- name: Upload artifact
|
|
227
|
+
uses: actions/upload-artifact@v4
|
|
228
|
+
with:
|
|
229
|
+
name: my-eol-report
|
|
230
|
+
path: herodevs.report.json
|
|
172
231
|
```
|
|
173
|
-
USAGE
|
|
174
|
-
$ hd scan sbom [--json] [-f <value>] [-d <value>] [-s] [-b]
|
|
175
|
-
|
|
176
|
-
FLAGS
|
|
177
|
-
-b, --background Run the scan in the background
|
|
178
|
-
-d, --dir=<value> The directory to scan in order to create a cyclonedx sbom
|
|
179
|
-
-f, --file=<value> The file path of an existing cyclonedx sbom to scan for EOL
|
|
180
|
-
-s, --save Save the generated SBOM as eol.sbom.json in the scanned directory
|
|
181
|
-
|
|
182
|
-
GLOBAL FLAGS
|
|
183
|
-
--json Format output as json.
|
|
184
232
|
|
|
185
|
-
|
|
186
|
-
|
|
233
|
+
#### GitLab CI/CD
|
|
234
|
+
|
|
235
|
+
```yaml
|
|
236
|
+
eol-scan:
|
|
237
|
+
image:
|
|
238
|
+
name: "ghcr.io/herodevs/eol-scan"
|
|
239
|
+
# Entrypoint or base command must be disabled due
|
|
240
|
+
# to GitLab's execution mechanism and run manually
|
|
241
|
+
entrypoint: [""]
|
|
242
|
+
script: "npx @herodevs/cli@beta scan eol -s"
|
|
243
|
+
artifacts:
|
|
244
|
+
paths:
|
|
245
|
+
- herodevs.report.json
|
|
246
|
+
```
|
|
187
247
|
|
|
188
|
-
|
|
189
|
-
$ hd scan sbom --dir=./my-project
|
|
248
|
+
### Using `npx` in CI
|
|
190
249
|
|
|
191
|
-
|
|
192
|
-
```
|
|
250
|
+
You can use `npx` to run the CLI in your CI pipeline, just like you would run it locally.
|
|
193
251
|
|
|
194
|
-
|
|
252
|
+
> [!NOTE]
|
|
253
|
+
> The development environment is expected to be ready to run the app. For best results,
|
|
254
|
+
prefer [using the prebuilt image](#using-the-docker-image-recommended), but otherwise, prepare
|
|
255
|
+
all requirements before the scan step.
|
|
195
256
|
|
|
196
|
-
|
|
257
|
+
#### GitHub Actions
|
|
197
258
|
|
|
198
|
-
|
|
259
|
+
```yaml
|
|
260
|
+
## .github/workflows/herodevs-eol-scan.yml
|
|
261
|
+
name: HeroDevs EOL Scan
|
|
199
262
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
263
|
+
on:
|
|
264
|
+
push:
|
|
265
|
+
branches: [ main ]
|
|
266
|
+
pull_request:
|
|
267
|
+
branches: [ main ]
|
|
203
268
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
269
|
+
jobs:
|
|
270
|
+
scan:
|
|
271
|
+
runs-on: ubuntu-latest
|
|
272
|
+
steps:
|
|
273
|
+
- uses: actions/checkout@v4
|
|
274
|
+
- uses: actions/setup-node@v4
|
|
275
|
+
with:
|
|
276
|
+
node-version: '20'
|
|
210
277
|
|
|
211
|
-
|
|
212
|
-
update the hd CLI
|
|
278
|
+
- run: echo # Prepare environment, install tooling, perform setup, etc.
|
|
213
279
|
|
|
214
|
-
|
|
215
|
-
|
|
280
|
+
- name: Run EOL Scan
|
|
281
|
+
run: npx @herodevs/cli@beta
|
|
216
282
|
|
|
217
|
-
|
|
283
|
+
- name: Upload artifact
|
|
284
|
+
uses: actions/upload-artifact@v4
|
|
285
|
+
with:
|
|
286
|
+
name: my-eol-report
|
|
287
|
+
path: herodevs.report.json
|
|
288
|
+
```
|
|
218
289
|
|
|
219
|
-
|
|
290
|
+
#### GitLab CI/CD
|
|
220
291
|
|
|
221
|
-
|
|
292
|
+
```yaml
|
|
293
|
+
image: alpine
|
|
222
294
|
|
|
223
|
-
|
|
295
|
+
eol-scan:
|
|
296
|
+
script:
|
|
297
|
+
- echo # Prepare environment, install tooling, perform setup, etc.
|
|
298
|
+
- npx @herodevs/cli@beta scan eol -s
|
|
299
|
+
artifacts:
|
|
300
|
+
paths:
|
|
301
|
+
- herodevs.report.json
|
|
302
|
+
```
|
|
224
303
|
|
|
225
|
-
|
|
304
|
+
## Local Docker image scans
|
|
226
305
|
|
|
227
|
-
|
|
306
|
+
The same pre-configured image can be pulled locally to scan in an optimized environment. Mount your code
|
|
307
|
+
to `/app` or a specified working directory to perform the scan:
|
|
228
308
|
|
|
229
|
-
|
|
309
|
+
```shell
|
|
310
|
+
docker run -v "$PWD":/app ghcr.io/herodevs/eol-scan
|
|
230
311
|
```
|
|
231
|
-
|
|
232
|
-
_See code: [@oclif/plugin-update](https://github.com/oclif/plugin-update/blob/v4.6.39/src/commands/update.ts)_
|
|
233
|
-
<!-- commandsstop -->
|
package/bin/dev.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
process.env.GRAPHQL_HOST = 'https://api.dev.nes.herodevs.com';
|
|
4
|
-
process.env.EOL_REPORT_URL = 'https://eol-report-card.stage.apps.herodevs.io/reports';
|
|
5
|
-
|
|
6
3
|
import main from './main.js';
|
|
7
4
|
|
|
8
5
|
try {
|
|
9
6
|
await main(false);
|
|
10
|
-
} catch
|
|
7
|
+
} catch {
|
|
11
8
|
process.exit(1);
|
|
12
9
|
}
|
package/bin/main.js
CHANGED
|
@@ -7,9 +7,9 @@ async function main(isProduction = false) {
|
|
|
7
7
|
strict: false, // Don't validate flags
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
-
// If no arguments at all, default to scan:eol
|
|
10
|
+
// If no arguments at all, default to scan:eol
|
|
11
11
|
if (positionals.length === 0) {
|
|
12
|
-
process.argv.splice(2, 0, 'scan:eol'
|
|
12
|
+
process.argv.splice(2, 0, 'scan:eol');
|
|
13
13
|
}
|
|
14
14
|
// If only flags are provided, set scan:eol as the command for those flags
|
|
15
15
|
else if (positionals.length === 1 && positionals[0].startsWith('-')) {
|
|
@@ -21,7 +21,7 @@ async function main(isProduction = false) {
|
|
|
21
21
|
development: !isProduction,
|
|
22
22
|
dir: new URL('./dev.js', import.meta.url),
|
|
23
23
|
});
|
|
24
|
-
} catch
|
|
24
|
+
} catch {
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
}
|
package/bin/run.js
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { gql } from '@apollo/client/core/core.cjs';
|
|
2
|
+
export const createReportMutation = gql `
|
|
3
|
+
mutation createReport($input: CreateEolReportInput) {
|
|
4
|
+
eol {
|
|
5
|
+
createReport(input: $input) {
|
|
6
|
+
success
|
|
7
|
+
id
|
|
8
|
+
totalRecords
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
`;
|
|
13
|
+
export const getEolReportQuery = gql `
|
|
14
|
+
query GetEolReport($input: GetEolReportInput) {
|
|
15
|
+
eol {
|
|
16
|
+
report(input: $input) {
|
|
17
|
+
id
|
|
18
|
+
createdOn
|
|
19
|
+
metadata
|
|
20
|
+
components {
|
|
21
|
+
purl
|
|
22
|
+
metadata
|
|
23
|
+
nesRemediation {
|
|
24
|
+
remediations {
|
|
25
|
+
urls {
|
|
26
|
+
main
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
page
|
|
32
|
+
totalRecords
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ApolloClient } from '@apollo/client/core/index.js';
|
|
2
|
+
import type { CreateEolReportInput, EolReport } from '@herodevs/eol-shared';
|
|
3
|
+
export declare const createApollo: (uri: string) => ApolloClient<import("@apollo/client/core/index.js").NormalizedCacheObject>;
|
|
4
|
+
export declare const SbomScanner: (client: ReturnType<typeof createApollo>) => (input: CreateEolReportInput) => Promise<EolReport>;
|
|
5
|
+
export declare class NesClient {
|
|
6
|
+
startScan: ReturnType<typeof SbomScanner>;
|
|
7
|
+
constructor(url: string);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Submit a scan for a list of purls
|
|
11
|
+
*/
|
|
12
|
+
export declare function submitScan(input: CreateEolReportInput): Promise<EolReport>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client/core/index.js';
|
|
2
|
+
import { config } from "../config/constants.js";
|
|
3
|
+
import { debugLogger } from "../service/log.svc.js";
|
|
4
|
+
import { stripTypename } from "../utils/strip-typename.js";
|
|
5
|
+
import { createReportMutation, getEolReportQuery } from "./gql-operations.js";
|
|
6
|
+
export const createApollo = (uri) => new ApolloClient({
|
|
7
|
+
cache: new InMemoryCache(),
|
|
8
|
+
defaultOptions: {
|
|
9
|
+
query: { fetchPolicy: 'no-cache' },
|
|
10
|
+
},
|
|
11
|
+
link: new HttpLink({
|
|
12
|
+
uri,
|
|
13
|
+
headers: {
|
|
14
|
+
'User-Agent': `hdcli/${process.env.npm_package_version ?? 'unknown'}`,
|
|
15
|
+
},
|
|
16
|
+
}),
|
|
17
|
+
});
|
|
18
|
+
export const SbomScanner = (client) => {
|
|
19
|
+
return async (input) => {
|
|
20
|
+
const res = await client.mutate({
|
|
21
|
+
mutation: createReportMutation,
|
|
22
|
+
variables: { input },
|
|
23
|
+
});
|
|
24
|
+
const result = res.data?.eol?.createReport;
|
|
25
|
+
if (!result?.success || !result.id) {
|
|
26
|
+
debugLogger('failed scan %o', result || {});
|
|
27
|
+
throw new Error('Failed to create EOL report');
|
|
28
|
+
}
|
|
29
|
+
const totalRecords = result.totalRecords || 0;
|
|
30
|
+
const totalPages = Math.ceil(totalRecords / config.pageSize);
|
|
31
|
+
const pages = Array.from({ length: totalPages }, (_, index) => client.query({
|
|
32
|
+
query: getEolReportQuery,
|
|
33
|
+
variables: {
|
|
34
|
+
input: {
|
|
35
|
+
id: result.id,
|
|
36
|
+
page: index + 1,
|
|
37
|
+
size: config.pageSize,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
}));
|
|
41
|
+
const components = [];
|
|
42
|
+
let reportMetadata = null;
|
|
43
|
+
for (let i = 0; i < pages.length; i += config.concurrentPageRequests) {
|
|
44
|
+
const batch = pages.slice(i, i + config.concurrentPageRequests);
|
|
45
|
+
const batchResponses = await Promise.all(batch);
|
|
46
|
+
for (const response of batchResponses) {
|
|
47
|
+
const report = response.data.eol.report;
|
|
48
|
+
reportMetadata ??= report;
|
|
49
|
+
components.push(...(report?.components ?? []));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (!reportMetadata) {
|
|
53
|
+
throw new Error('Failed to fetch EOL report');
|
|
54
|
+
}
|
|
55
|
+
return stripTypename({
|
|
56
|
+
...reportMetadata,
|
|
57
|
+
components,
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
export class NesClient {
|
|
62
|
+
startScan;
|
|
63
|
+
constructor(url) {
|
|
64
|
+
this.startScan = SbomScanner(createApollo(url));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Submit a scan for a list of purls
|
|
69
|
+
*/
|
|
70
|
+
export function submitScan(input) {
|
|
71
|
+
const url = config.graphqlHost + config.graphqlPath;
|
|
72
|
+
debugLogger('Submitting scan to %s', url);
|
|
73
|
+
const client = new NesClient(url);
|
|
74
|
+
return client.startScan(input);
|
|
75
|
+
}
|
|
@@ -1,31 +1,25 @@
|
|
|
1
|
+
import type { EolReport } from '@herodevs/eol-shared';
|
|
1
2
|
import { Command } from '@oclif/core';
|
|
2
|
-
import type { InsightsEolScanComponent } from '../../api/types/nes.types.ts';
|
|
3
3
|
export default class ScanEol extends Command {
|
|
4
4
|
static description: string;
|
|
5
5
|
static enableJsonFlag: boolean;
|
|
6
|
-
static examples:
|
|
6
|
+
static examples: {
|
|
7
|
+
description: string;
|
|
8
|
+
command: string;
|
|
9
|
+
}[];
|
|
7
10
|
static flags: {
|
|
8
11
|
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
-
|
|
10
|
-
dir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
dir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
13
|
save: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
saveSbom: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
version: import("@oclif/core/interfaces").BooleanFlag<void>;
|
|
14
16
|
};
|
|
15
|
-
run(): Promise<
|
|
16
|
-
|
|
17
|
-
}>;
|
|
18
|
-
private getScan;
|
|
19
|
-
private getPurlsFromFile;
|
|
20
|
-
private printWebReportUrl;
|
|
17
|
+
run(): Promise<EolReport | undefined>;
|
|
18
|
+
private loadSbom;
|
|
21
19
|
private scanSbom;
|
|
22
|
-
private getFilteredComponents;
|
|
23
20
|
private saveReport;
|
|
21
|
+
private saveSbom;
|
|
24
22
|
private displayResults;
|
|
25
|
-
private
|
|
26
|
-
private
|
|
27
|
-
private displayNoComponentsMessage;
|
|
28
|
-
private logLine;
|
|
29
|
-
private displayStatusSection;
|
|
30
|
-
private logLegend;
|
|
23
|
+
private getSbomFromScan;
|
|
24
|
+
private getSbomFromFile;
|
|
31
25
|
}
|