@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.
Files changed (69) hide show
  1. package/README.md +187 -109
  2. package/bin/dev.js +1 -4
  3. package/bin/main.js +3 -3
  4. package/bin/run.js +1 -1
  5. package/dist/api/gql-operations.d.ts +2 -0
  6. package/dist/api/gql-operations.js +36 -0
  7. package/dist/api/nes.client.d.ts +12 -0
  8. package/dist/api/nes.client.js +75 -0
  9. package/dist/commands/scan/eol.d.ts +13 -19
  10. package/dist/commands/scan/eol.js +163 -149
  11. package/dist/config/constants.d.ts +9 -2
  12. package/dist/config/constants.js +19 -2
  13. package/dist/hooks/finally/finally.d.ts +3 -0
  14. package/dist/hooks/finally/finally.js +18 -0
  15. package/dist/hooks/{npm-update-notifier.js → init/00_npm-update-notifier.js} +3 -3
  16. package/dist/hooks/init/01_initialize_amplitude.d.ts +3 -0
  17. package/dist/hooks/init/01_initialize_amplitude.js +15 -0
  18. package/dist/service/analytics.svc.d.ts +28 -0
  19. package/dist/service/analytics.svc.js +112 -0
  20. package/dist/service/{eol/cdx.svc.d.ts → cdx.svc.d.ts} +8 -16
  21. package/dist/service/{eol/cdx.svc.js → cdx.svc.js} +17 -7
  22. package/dist/service/display.svc.d.ts +22 -0
  23. package/dist/service/display.svc.js +72 -0
  24. package/dist/service/file.svc.d.ts +20 -0
  25. package/dist/service/file.svc.js +71 -0
  26. package/dist/service/log.svc.d.ts +1 -0
  27. package/dist/service/log.svc.js +9 -0
  28. package/dist/service/{eol/sbom.worker.js → sbom.worker.js} +2 -1
  29. package/dist/utils/strip-typename.d.ts +1 -0
  30. package/dist/utils/strip-typename.js +15 -0
  31. package/package.json +33 -22
  32. package/dist/api/client.d.ts +0 -12
  33. package/dist/api/client.js +0 -43
  34. package/dist/api/nes/nes.client.d.ts +0 -23
  35. package/dist/api/nes/nes.client.js +0 -107
  36. package/dist/api/queries/nes/sbom.d.ts +0 -3
  37. package/dist/api/queries/nes/sbom.js +0 -35
  38. package/dist/api/queries/nes/telemetry.d.ts +0 -2
  39. package/dist/api/queries/nes/telemetry.js +0 -24
  40. package/dist/api/types/hd-cli.types.d.ts +0 -30
  41. package/dist/api/types/hd-cli.types.js +0 -10
  42. package/dist/api/types/nes.types.d.ts +0 -53
  43. package/dist/api/types/nes.types.js +0 -1
  44. package/dist/commands/report/committers.d.ts +0 -23
  45. package/dist/commands/report/committers.js +0 -146
  46. package/dist/commands/report/purls.d.ts +0 -15
  47. package/dist/commands/report/purls.js +0 -84
  48. package/dist/commands/scan/sbom.d.ts +0 -21
  49. package/dist/commands/scan/sbom.js +0 -159
  50. package/dist/service/committers.svc.d.ts +0 -70
  51. package/dist/service/committers.svc.js +0 -196
  52. package/dist/service/eol/eol.svc.d.ts +0 -14
  53. package/dist/service/eol/eol.svc.js +0 -49
  54. package/dist/service/error.svc.d.ts +0 -8
  55. package/dist/service/error.svc.js +0 -28
  56. package/dist/service/nes/nes.svc.d.ts +0 -5
  57. package/dist/service/nes/nes.svc.js +0 -27
  58. package/dist/service/purls.svc.d.ts +0 -23
  59. package/dist/service/purls.svc.js +0 -99
  60. package/dist/ui/date.ui.d.ts +0 -1
  61. package/dist/ui/date.ui.js +0 -15
  62. package/dist/ui/eol.ui.d.ts +0 -15
  63. package/dist/ui/eol.ui.js +0 -113
  64. package/dist/ui/shared.ui.d.ts +0 -6
  65. package/dist/ui/shared.ui.js +0 -16
  66. /package/dist/hooks/{npm-update-notifier.d.ts → init/00_npm-update-notifier.d.ts} +0 -0
  67. /package/dist/hooks/{prerun.d.ts → prerun/prerun.d.ts} +0 -0
  68. /package/dist/hooks/{prerun.js → prerun/prerun.js} +0 -0
  69. /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's scanning commands (`hd scan eol` and `hd scan sbom`) are designed to be non-invasive:
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
- * They do not install dependencies or modify package manager files (package-lock.json, yarn.lock, etc.)
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.0 linux-x64 node-v22.15.0
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.28/src/commands/help.ts)_
106
+ _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.32/src/commands/help.ts)_
68
107
 
69
- ## `hd report committers`
108
+ ## `hd scan eol`
70
109
 
71
- Generate report of committers to a git repository
110
+ Scan a given SBOM for EOL data
72
111
 
73
112
  ```
74
113
  USAGE
75
- $ hd report committers [--json] [-m <value>] [-c] [-s]
114
+ $ hd scan eol [--json] [-f <value> | -d <value>] [-s] [--saveSbom] [--version]
76
115
 
77
116
  FLAGS
78
- -c, --csv Output in CSV format
79
- -m, --months=<value> [default: 12] The number of months of git history to review
80
- -s, --save Save the committers report as eol.committers.<output>
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
- Generate report of committers to a git repository
127
+ Scan a given SBOM for EOL data
87
128
 
88
129
  EXAMPLES
89
- $ hd report committers
130
+ Default behavior (no command or flags specified)
131
+
132
+ $ hd
133
+
134
+ Equivalent to
135
+
136
+ $ hd scan eol --dir .
90
137
 
91
- $ hd report committers --csv -s
138
+ Skip SBOM generation and specify an existing file
92
139
 
93
- $ hd report committers --json
140
+ $ hd scan eol --file /path/to/sbom.json
94
141
 
95
- $ hd report committers --csv
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/report/committers.ts](https://github.com/herodevs/cli/blob/v2.0.0-beta.0/src/commands/report/committers.ts)_
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 report purls`
153
+ ## `hd update [CHANNEL]`
154
+
155
+ update the hd CLI
101
156
 
102
- Generate a list of purls from a sbom
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 report purls [--json] [-f <value>] [-d <value>] [-s] [-c]
161
+ $ hd update [CHANNEL] [--force | | [-a | -v <value> | -i]] [-b ]
107
162
 
108
163
  FLAGS
109
- -c, --csv Save output in CSV format (only applies when using --save)
110
- -d, --dir=<value> The directory to scan in order to create a cyclonedx sbom
111
- -f, --file=<value> The file path of an existing cyclonedx sbom to scan for EOL
112
- -s, --save Save the list of purls as eol.purls.<output>
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
- Generate a list of purls from a sbom
171
+ update the hd CLI
119
172
 
120
173
  EXAMPLES
121
- $ hd report purls --json -s
122
-
123
- $ hd report purls --dir=./my-project
174
+ Update to the stable channel:
124
175
 
125
- $ hd report purls --file=path/to/sbom.json
176
+ $ hd update stable
126
177
 
127
- $ hd report purls --dir=./my-project --save
178
+ Update to a specific version:
128
179
 
129
- $ hd report purls --save --csv
130
- ```
180
+ $ hd update --version 1.0.0
131
181
 
132
- _See code: [src/commands/report/purls.ts](https://github.com/herodevs/cli/blob/v2.0.0-beta.0/src/commands/report/purls.ts)_
182
+ Interactively select version:
133
183
 
134
- ## `hd scan eol`
184
+ $ hd update --interactive
135
185
 
136
- Scan a given sbom for EOL data
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
- GLOBAL FLAGS
151
- --json Format output as json.
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
- DESCRIPTION
154
- Scan a given sbom for EOL data
194
+ ## CI/CD Usage
155
195
 
156
- EXAMPLES
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
- $ hd scan eol --file=path/to/sbom.json
198
+ ### Using the Docker Image (Recommended)
160
199
 
161
- $ hd scan eol --purls=path/to/purls.json
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
- $ hd scan eol -a --dir=./my-project
164
- ```
203
+ #### GitHub Actions
165
204
 
166
- _See code: [src/commands/scan/eol.ts](https://github.com/herodevs/cli/blob/v2.0.0-beta.0/src/commands/scan/eol.ts)_
205
+ ```yaml
206
+ ## .github/workflows/herodevs-eol-scan.yml
207
+ name: HeroDevs EOL Scan
167
208
 
168
- ## `hd scan sbom`
209
+ on:
210
+ push:
211
+ branches: [ main ]
212
+ pull_request:
213
+ branches: [ main ]
169
214
 
170
- Scan a SBOM for purls
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
- DESCRIPTION
186
- Scan a SBOM for purls
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
- EXAMPLES
189
- $ hd scan sbom --dir=./my-project
248
+ ### Using `npx` in CI
190
249
 
191
- $ hd scan sbom --file=path/to/sbom.json
192
- ```
250
+ You can use `npx` to run the CLI in your CI pipeline, just like you would run it locally.
193
251
 
194
- _See code: [src/commands/scan/sbom.ts](https://github.com/herodevs/cli/blob/v2.0.0-beta.0/src/commands/scan/sbom.ts)_
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
- ## `hd update [CHANNEL]`
257
+ #### GitHub Actions
197
258
 
198
- update the hd CLI
259
+ ```yaml
260
+ ## .github/workflows/herodevs-eol-scan.yml
261
+ name: HeroDevs EOL Scan
199
262
 
200
- ```
201
- USAGE
202
- $ hd update [CHANNEL] [--force | | [-a | -v <value> | -i]] [-b ]
263
+ on:
264
+ push:
265
+ branches: [ main ]
266
+ pull_request:
267
+ branches: [ main ]
203
268
 
204
- FLAGS
205
- -a, --available See available versions.
206
- -b, --verbose Show more details about the available versions.
207
- -i, --interactive Interactively select version to install. This is ignored if a channel is provided.
208
- -v, --version=<value> Install a specific version.
209
- --force Force a re-download of the requested version.
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
- DESCRIPTION
212
- update the hd CLI
278
+ - run: echo # Prepare environment, install tooling, perform setup, etc.
213
279
 
214
- EXAMPLES
215
- Update to the stable channel:
280
+ - name: Run EOL Scan
281
+ run: npx @herodevs/cli@beta
216
282
 
217
- $ hd update stable
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
- Update to a specific version:
290
+ #### GitLab CI/CD
220
291
 
221
- $ hd update --version 1.0.0
292
+ ```yaml
293
+ image: alpine
222
294
 
223
- Interactively select version:
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
- $ hd update --interactive
304
+ ## Local Docker image scans
226
305
 
227
- See available versions:
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
- $ hd update --available
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 (error) {
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 -t
10
+ // If no arguments at all, default to scan:eol
11
11
  if (positionals.length === 0) {
12
- process.argv.splice(2, 0, 'scan:eol', '-t');
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 (error) {
24
+ } catch {
25
25
  process.exit(1);
26
26
  }
27
27
  }
package/bin/run.js CHANGED
@@ -4,6 +4,6 @@ import main from './main.js';
4
4
 
5
5
  try {
6
6
  await main(true);
7
- } catch (error) {
7
+ } catch {
8
8
  process.exit(1);
9
9
  }
@@ -0,0 +1,2 @@
1
+ export declare const createReportMutation: import("graphql/language/ast.js").DocumentNode;
2
+ export declare const getEolReportQuery: import("graphql/language/ast.js").DocumentNode;
@@ -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: string[];
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
- purls: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
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
- all: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
- table: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ saveSbom: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ version: import("@oclif/core/interfaces").BooleanFlag<void>;
14
16
  };
15
- run(): Promise<{
16
- components: InsightsEolScanComponent[];
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 displayResultsInTable;
26
- private displayTable;
27
- private displayNoComponentsMessage;
28
- private logLine;
29
- private displayStatusSection;
30
- private logLegend;
23
+ private getSbomFromScan;
24
+ private getSbomFromFile;
31
25
  }