@herodevs/cli 0.3.1 → 1.0.0-beta.1

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 (273) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +146 -6
  3. package/bin/dev.cmd +3 -0
  4. package/bin/dev.js +11 -0
  5. package/bin/run.cmd +3 -0
  6. package/bin/run.js +4 -0
  7. package/dist/api/client.d.ts +14 -0
  8. package/dist/api/client.js +42 -0
  9. package/dist/api/nes/nes.client.d.ts +16 -0
  10. package/dist/api/nes/nes.client.js +17 -0
  11. package/dist/api/queries/nes/sbom.d.ts +3 -0
  12. package/dist/api/queries/nes/sbom.js +29 -0
  13. package/{report-ingestion/src/lib/queries.d.ts → dist/api/queries/nes/telemetry.d.ts} +2 -2
  14. package/{report-ingestion/src/lib/queries.js → dist/api/queries/nes/telemetry.js} +3 -7
  15. package/dist/api/types/nes.types.d.ts +35 -0
  16. package/dist/api/types/nes.types.js +1 -0
  17. package/dist/commands/report/committers.d.ts +22 -0
  18. package/dist/commands/report/committers.js +104 -0
  19. package/dist/commands/report/purls.d.ts +13 -0
  20. package/dist/commands/report/purls.js +66 -0
  21. package/dist/commands/scan/eol.d.ts +16 -0
  22. package/dist/commands/scan/eol.js +71 -0
  23. package/dist/commands/scan/sbom.d.ts +18 -0
  24. package/dist/commands/scan/sbom.js +106 -0
  25. package/dist/config/update.d.ts +3 -0
  26. package/dist/config/update.js +7 -0
  27. package/dist/hooks/init/update.d.ts +2 -0
  28. package/dist/hooks/init/update.js +5 -0
  29. package/dist/hooks/prerun/CommandContextHook.d.ts +3 -0
  30. package/dist/hooks/prerun/CommandContextHook.js +8 -0
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.js +1 -0
  33. package/dist/service/committers.svc.d.ts +70 -0
  34. package/dist/service/committers.svc.js +175 -0
  35. package/dist/service/eol/cdx.svc.d.ts +22 -0
  36. package/dist/service/eol/cdx.svc.js +86 -0
  37. package/dist/service/eol/eol.svc.d.ts +34 -0
  38. package/dist/service/eol/eol.svc.js +86 -0
  39. package/dist/service/line.svc.d.ts +24 -0
  40. package/dist/service/line.svc.js +61 -0
  41. package/dist/service/log.svc.d.ts +10 -0
  42. package/dist/service/log.svc.js +20 -0
  43. package/dist/service/nes/nes.svc.d.ts +4 -0
  44. package/dist/service/nes/nes.svc.js +25 -0
  45. package/dist/service/purls.svc.d.ts +17 -0
  46. package/dist/service/purls.svc.js +29 -0
  47. package/dist/ui/eol.ui.d.ts +3 -0
  48. package/dist/ui/eol.ui.js +17 -0
  49. package/package.json +73 -16
  50. package/core-types/README.md +0 -11
  51. package/core-types/package.json +0 -12
  52. package/core-types/src/index.d.ts +0 -1
  53. package/core-types/src/index.js +0 -5
  54. package/core-types/src/index.js.map +0 -1
  55. package/core-types/src/lib/project-type.d.ts +0 -1
  56. package/core-types/src/lib/project-type.js +0 -3
  57. package/core-types/src/lib/project-type.js.map +0 -1
  58. package/init/README.md +0 -11
  59. package/init/package.json +0 -18
  60. package/init/src/index.d.ts +0 -1
  61. package/init/src/index.js +0 -5
  62. package/init/src/index.js.map +0 -1
  63. package/init/src/lib/configure-project.d.ts +0 -3
  64. package/init/src/lib/configure-project.js +0 -10
  65. package/init/src/lib/configure-project.js.map +0 -1
  66. package/init/src/lib/get-package-choices.d.ts +0 -2
  67. package/init/src/lib/get-package-choices.js +0 -16
  68. package/init/src/lib/get-package-choices.js.map +0 -1
  69. package/init/src/lib/get-product-choices.d.ts +0 -2
  70. package/init/src/lib/get-product-choices.js +0 -29
  71. package/init/src/lib/get-product-choices.js.map +0 -1
  72. package/init/src/lib/get-release-trains.d.ts +0 -2
  73. package/init/src/lib/get-release-trains.js +0 -57
  74. package/init/src/lib/get-release-trains.js.map +0 -1
  75. package/init/src/lib/init.d.ts +0 -5
  76. package/init/src/lib/init.js +0 -72
  77. package/init/src/lib/init.js.map +0 -1
  78. package/init/src/lib/mock-trains.d.ts +0 -2
  79. package/init/src/lib/mock-trains.js +0 -190
  80. package/init/src/lib/mock-trains.js.map +0 -1
  81. package/init/src/lib/models/choice.d.ts +0 -4
  82. package/init/src/lib/models/choice.js +0 -3
  83. package/init/src/lib/models/choice.js.map +0 -1
  84. package/init/src/lib/models/entry.d.ts +0 -6
  85. package/init/src/lib/models/entry.js +0 -3
  86. package/init/src/lib/models/entry.js.map +0 -1
  87. package/init/src/lib/models/index.d.ts +0 -5
  88. package/init/src/lib/models/index.js +0 -9
  89. package/init/src/lib/models/index.js.map +0 -1
  90. package/init/src/lib/models/package-version.d.ts +0 -14
  91. package/init/src/lib/models/package-version.js +0 -3
  92. package/init/src/lib/models/package-version.js.map +0 -1
  93. package/init/src/lib/models/product.d.ts +0 -5
  94. package/init/src/lib/models/product.js +0 -3
  95. package/init/src/lib/models/product.js.map +0 -1
  96. package/init/src/lib/models/release-train.d.ts +0 -9
  97. package/init/src/lib/models/release-train.js +0 -3
  98. package/init/src/lib/models/release-train.js.map +0 -1
  99. package/init/src/lib/npm/configure-npm-project.d.ts +0 -2
  100. package/init/src/lib/npm/configure-npm-project.js +0 -59
  101. package/init/src/lib/npm/configure-npm-project.js.map +0 -1
  102. package/init/src/lib/verify-project-type.d.ts +0 -6
  103. package/init/src/lib/verify-project-type.js +0 -19
  104. package/init/src/lib/verify-project-type.js.map +0 -1
  105. package/report-committers/README.md +0 -11
  106. package/report-committers/package.json +0 -15
  107. package/report-committers/src/index.d.ts +0 -1
  108. package/report-committers/src/index.js +0 -5
  109. package/report-committers/src/index.js.map +0 -1
  110. package/report-committers/src/lib/committers.d.ts +0 -11
  111. package/report-committers/src/lib/committers.js +0 -106
  112. package/report-committers/src/lib/committers.js.map +0 -1
  113. package/report-committers/src/lib/constants.d.ts +0 -4
  114. package/report-committers/src/lib/constants.js +0 -8
  115. package/report-committers/src/lib/constants.js.map +0 -1
  116. package/report-committers/src/lib/get-committer-counts.d.ts +0 -3
  117. package/report-committers/src/lib/get-committer-counts.js +0 -33
  118. package/report-committers/src/lib/get-committer-counts.js.map +0 -1
  119. package/report-committers/src/lib/parse-date-flags.d.ts +0 -4
  120. package/report-committers/src/lib/parse-date-flags.js +0 -11
  121. package/report-committers/src/lib/parse-date-flags.js.map +0 -1
  122. package/report-committers/src/lib/parse-git-log-entries.d.ts +0 -2
  123. package/report-committers/src/lib/parse-git-log-entries.js +0 -11
  124. package/report-committers/src/lib/parse-git-log-entries.js.map +0 -1
  125. package/report-committers/src/lib/parse-monthly.d.ts +0 -4
  126. package/report-committers/src/lib/parse-monthly.js +0 -56
  127. package/report-committers/src/lib/parse-monthly.js.map +0 -1
  128. package/report-committers/src/lib/types.d.ts +0 -27
  129. package/report-committers/src/lib/types.js +0 -3
  130. package/report-committers/src/lib/types.js.map +0 -1
  131. package/report-diagnostics/README.md +0 -11
  132. package/report-diagnostics/package.json +0 -15
  133. package/report-diagnostics/src/index.d.ts +0 -1
  134. package/report-diagnostics/src/index.js +0 -5
  135. package/report-diagnostics/src/index.js.map +0 -1
  136. package/report-diagnostics/src/lib/diagnostics.d.ts +0 -7
  137. package/report-diagnostics/src/lib/diagnostics.js +0 -94
  138. package/report-diagnostics/src/lib/diagnostics.js.map +0 -1
  139. package/report-diagnostics/src/lib/get-diagnostic-types.d.ts +0 -4
  140. package/report-diagnostics/src/lib/get-diagnostic-types.js +0 -15
  141. package/report-diagnostics/src/lib/get-diagnostic-types.js.map +0 -1
  142. package/report-diagnostics/src/lib/get-file-contents.d.ts +0 -1
  143. package/report-diagnostics/src/lib/get-file-contents.js +0 -12
  144. package/report-diagnostics/src/lib/get-file-contents.js.map +0 -1
  145. package/report-diagnostics/src/lib/get-package-json-section.d.ts +0 -1
  146. package/report-diagnostics/src/lib/get-package-json-section.js +0 -15
  147. package/report-diagnostics/src/lib/get-package-json-section.js.map +0 -1
  148. package/report-ingestion/README.md +0 -11
  149. package/report-ingestion/package.json +0 -13
  150. package/report-ingestion/src/index.d.ts +0 -1
  151. package/report-ingestion/src/index.js +0 -5
  152. package/report-ingestion/src/index.js.map +0 -1
  153. package/report-ingestion/src/lib/ingestion.d.ts +0 -3
  154. package/report-ingestion/src/lib/ingestion.js +0 -40
  155. package/report-ingestion/src/lib/ingestion.js.map +0 -1
  156. package/report-ingestion/src/lib/prompts.d.ts +0 -5
  157. package/report-ingestion/src/lib/prompts.js +0 -46
  158. package/report-ingestion/src/lib/prompts.js.map +0 -1
  159. package/report-ingestion/src/lib/queries.js.map +0 -1
  160. package/report-ingestion/src/lib/send-manifest.d.ts +0 -10
  161. package/report-ingestion/src/lib/send-manifest.js +0 -129
  162. package/report-ingestion/src/lib/send-manifest.js.map +0 -1
  163. package/report-ingestion/src/lib/types.d.ts +0 -6
  164. package/report-ingestion/src/lib/types.js +0 -3
  165. package/report-ingestion/src/lib/types.js.map +0 -1
  166. package/sea-config.json +0 -5
  167. package/src/lib/cli.d.ts +0 -1
  168. package/src/lib/cli.js +0 -22
  169. package/src/lib/cli.js.map +0 -1
  170. package/src/lib/create-group-command.d.ts +0 -2
  171. package/src/lib/create-group-command.js +0 -28
  172. package/src/lib/create-group-command.js.map +0 -1
  173. package/src/lib/ensure-version.d.ts +0 -2
  174. package/src/lib/ensure-version.js +0 -71
  175. package/src/lib/ensure-version.js.map +0 -1
  176. package/src/lib/get-commands.d.ts +0 -2
  177. package/src/lib/get-commands.js +0 -27
  178. package/src/lib/get-commands.js.map +0 -1
  179. package/src/lib/log-colors.d.ts +0 -28
  180. package/src/lib/log-colors.js +0 -9
  181. package/src/lib/log-colors.js.map +0 -1
  182. package/src/main.d.ts +0 -2
  183. package/src/main.js +0 -6
  184. package/src/main.js.map +0 -1
  185. package/tracker-init/README.md +0 -11
  186. package/tracker-init/package.json +0 -15
  187. package/tracker-init/src/index.d.ts +0 -1
  188. package/tracker-init/src/index.js +0 -5
  189. package/tracker-init/src/index.js.map +0 -1
  190. package/tracker-init/src/lib/default-config.d.ts +0 -2
  191. package/tracker-init/src/lib/default-config.js +0 -20
  192. package/tracker-init/src/lib/default-config.js.map +0 -1
  193. package/tracker-init/src/lib/init.d.ts +0 -5
  194. package/tracker-init/src/lib/init.js +0 -25
  195. package/tracker-init/src/lib/init.js.map +0 -1
  196. package/tracker-run/README.md +0 -11
  197. package/tracker-run/package.json +0 -18
  198. package/tracker-run/src/index.d.ts +0 -1
  199. package/tracker-run/src/index.js +0 -5
  200. package/tracker-run/src/index.js.map +0 -1
  201. package/tracker-run/src/lib/get-data-filepath.d.ts +0 -1
  202. package/tracker-run/src/lib/get-data-filepath.js +0 -8
  203. package/tracker-run/src/lib/get-data-filepath.js.map +0 -1
  204. package/tracker-run/src/lib/get-data.d.ts +0 -1
  205. package/tracker-run/src/lib/get-data.js +0 -14
  206. package/tracker-run/src/lib/get-data.js.map +0 -1
  207. package/tracker-run/src/lib/get-git-commit.d.ts +0 -4
  208. package/tracker-run/src/lib/get-git-commit.js +0 -32
  209. package/tracker-run/src/lib/get-git-commit.js.map +0 -1
  210. package/tracker-run/src/lib/process-category.d.ts +0 -2
  211. package/tracker-run/src/lib/process-category.js +0 -151
  212. package/tracker-run/src/lib/process-category.js.map +0 -1
  213. package/tracker-run/src/lib/process-config.d.ts +0 -2
  214. package/tracker-run/src/lib/process-config.js +0 -19
  215. package/tracker-run/src/lib/process-config.js.map +0 -1
  216. package/tracker-run/src/lib/run.d.ts +0 -7
  217. package/tracker-run/src/lib/run.js +0 -29
  218. package/tracker-run/src/lib/run.js.map +0 -1
  219. package/tracker-run/src/lib/save-results.d.ts +0 -2
  220. package/tracker-run/src/lib/save-results.js +0 -19
  221. package/tracker-run/src/lib/save-results.js.map +0 -1
  222. package/tracker-shared/README.md +0 -11
  223. package/tracker-shared/package.json +0 -12
  224. package/tracker-shared/src/index.d.ts +0 -2
  225. package/tracker-shared/src/index.js +0 -14
  226. package/tracker-shared/src/index.js.map +0 -1
  227. package/tracker-shared/src/lib/models/aggregate-result.d.ts +0 -4
  228. package/tracker-shared/src/lib/models/aggregate-result.js +0 -3
  229. package/tracker-shared/src/lib/models/aggregate-result.js.map +0 -1
  230. package/tracker-shared/src/lib/models/category-result.d.ts +0 -7
  231. package/tracker-shared/src/lib/models/category-result.js +0 -3
  232. package/tracker-shared/src/lib/models/category-result.js.map +0 -1
  233. package/tracker-shared/src/lib/models/category.d.ts +0 -9
  234. package/tracker-shared/src/lib/models/category.js +0 -3
  235. package/tracker-shared/src/lib/models/category.js.map +0 -1
  236. package/tracker-shared/src/lib/models/config.d.ts +0 -8
  237. package/tracker-shared/src/lib/models/config.js +0 -3
  238. package/tracker-shared/src/lib/models/config.js.map +0 -1
  239. package/tracker-shared/src/lib/models/file-result.d.ts +0 -5
  240. package/tracker-shared/src/lib/models/file-result.js +0 -3
  241. package/tracker-shared/src/lib/models/file-result.js.map +0 -1
  242. package/tracker-shared/src/lib/models/index.d.ts +0 -8
  243. package/tracker-shared/src/lib/models/index.js +0 -12
  244. package/tracker-shared/src/lib/models/index.js.map +0 -1
  245. package/tracker-shared/src/lib/models/process-result.d.ts +0 -6
  246. package/tracker-shared/src/lib/models/process-result.js +0 -3
  247. package/tracker-shared/src/lib/models/process-result.js.map +0 -1
  248. package/tracker-shared/src/lib/models/result.d.ts +0 -11
  249. package/tracker-shared/src/lib/models/result.js +0 -3
  250. package/tracker-shared/src/lib/models/result.js.map +0 -1
  251. package/tracker-shared/src/lib/models/total-result.d.ts +0 -4
  252. package/tracker-shared/src/lib/models/total-result.js +0 -3
  253. package/tracker-shared/src/lib/models/total-result.js.map +0 -1
  254. package/tracker-shared/src/lib/read-config.d.ts +0 -2
  255. package/tracker-shared/src/lib/read-config.js +0 -13
  256. package/tracker-shared/src/lib/read-config.js.map +0 -1
  257. package/utility/README.md +0 -11
  258. package/utility/package.json +0 -13
  259. package/utility/src/index.d.ts +0 -4
  260. package/utility/src/index.js +0 -8
  261. package/utility/src/index.js.map +0 -1
  262. package/utility/src/lib/get-project-types.d.ts +0 -2
  263. package/utility/src/lib/get-project-types.js +0 -13
  264. package/utility/src/lib/get-project-types.js.map +0 -1
  265. package/utility/src/lib/get-root-dir.d.ts +0 -1
  266. package/utility/src/lib/get-root-dir.js +0 -12
  267. package/utility/src/lib/get-root-dir.js.map +0 -1
  268. package/utility/src/lib/run-command.d.ts +0 -1
  269. package/utility/src/lib/run-command.js +0 -31
  270. package/utility/src/lib/run-command.js.map +0 -1
  271. package/utility/src/lib/sort-by-name.d.ts +0 -3
  272. package/utility/src/lib/sort-by-name.js +0 -7
  273. package/utility/src/lib/sort-by-name.js.map +0 -1
@@ -0,0 +1,86 @@
1
+ import { NesApolloClient } from "../../api/nes/nes.client.js";
2
+ import { log } from "../../service/log.svc.js";
3
+ import { getDaysEolFromEolAt, getStatusFromComponent } from "../line.svc.js";
4
+ import { extractPurls } from "../purls.svc.js";
5
+ import { createBomFromDir } from "./cdx.svc.js";
6
+ export async function createSbom(directory, opts = {}) {
7
+ const sbom = await createBomFromDir(directory, opts.cdxgen || {});
8
+ if (!sbom)
9
+ throw new Error('SBOM not generated');
10
+ log.info('SBOM generated');
11
+ return sbom;
12
+ }
13
+ export function validateIsCycloneDxSbom(sbom) {
14
+ if (!sbom || typeof sbom !== 'object') {
15
+ throw new Error('SBOM must be an object');
16
+ }
17
+ const s = sbom;
18
+ // Basic CycloneDX validation
19
+ if (!('bomFormat' in s) || s.bomFormat !== 'CycloneDX') {
20
+ throw new Error('Invalid SBOM format: must be CycloneDX');
21
+ }
22
+ if (!('specVersion' in s) || typeof s.specVersion !== 'string') {
23
+ throw new Error('Invalid SBOM: missing specVersion');
24
+ }
25
+ if (!('components' in s) || !Array.isArray(s.components)) {
26
+ throw new Error('Invalid SBOM: missing or invalid components array');
27
+ }
28
+ }
29
+ /**
30
+ * Main function to scan directory and collect SBOM data
31
+ */
32
+ export async function scanForEol(sbom) {
33
+ const purls = await extractPurls(sbom);
34
+ const scan = await submitScan(purls);
35
+ return { purls, scan };
36
+ }
37
+ /**
38
+ * Uses the purls from the sbom to run the scan.
39
+ */
40
+ export async function submitScan(purls) {
41
+ // NOTE: GRAPHQL_HOST is set in `./bin/dev.js` or tests
42
+ const host = process.env.GRAPHQL_HOST || 'https://api.nes.herodevs.com';
43
+ const path = process.env.GRAPHQL_PATH || '/graphql';
44
+ const url = host + path;
45
+ const client = new NesApolloClient(url);
46
+ const scan = await client.scan.sbom(purls);
47
+ return scan;
48
+ }
49
+ /**
50
+ * Work in progress; creates "rows" for each component
51
+ * based on the model + the scan result from NES.
52
+ *
53
+ * The idea being that each row can easily be used for
54
+ * processing and/or rendering.
55
+ */
56
+ export async function prepareRows(purls, scan) {
57
+ const lines = [];
58
+ for (const purl of purls) {
59
+ const details = scan.components.get(purl);
60
+ if (!details) {
61
+ // In this case, the purl string is in the generated sbom, but the NES/XEOL api has no data
62
+ // TODO: add UNKNOWN Component Status, create new line, and create flag to show/hide unknown results
63
+ log.debug(`Unknown status: ${purl}.`);
64
+ continue;
65
+ }
66
+ const { info } = details;
67
+ // Handle date deserialization from GraphQL
68
+ if (typeof info.eolAt === 'string' && info.eolAt) {
69
+ info.eolAt = new Date(info.eolAt);
70
+ }
71
+ const daysEol = getDaysEolFromEolAt(info.eolAt);
72
+ const status = getStatusFromComponent(details, daysEol);
73
+ const showOk = process.env.SHOW_OK === 'true';
74
+ if (!showOk && status === 'OK') {
75
+ continue;
76
+ }
77
+ lines.push({
78
+ daysEol,
79
+ info,
80
+ purl,
81
+ status,
82
+ });
83
+ }
84
+ return lines;
85
+ }
86
+ export { cdxgen } from "./cdx.svc.js";
@@ -0,0 +1,24 @@
1
+ import type { ComponentStatus, ScanResultComponent } from '../api/types/nes.types.ts';
2
+ export interface Line {
3
+ daysEol: number | null;
4
+ purl: ScanResultComponent['purl'];
5
+ info: {
6
+ eolAt: Date | null;
7
+ isEol: boolean;
8
+ };
9
+ status: ComponentStatus;
10
+ }
11
+ export declare function getStatusFromComponent(component: ScanResultComponent, daysEol: number | null): ComponentStatus;
12
+ export declare function daysBetween(date1: Date, date2: Date): number;
13
+ export declare function getDaysEolFromEolAt(eolAt: Date | null): number | null;
14
+ export declare function getMessageAndStatus(status: string, daysEol: number | null): {
15
+ stat: string;
16
+ msg: string;
17
+ };
18
+ export declare function formatLine(l: Line, idx: number, ctx: {
19
+ longest: number;
20
+ total: number;
21
+ }): {
22
+ name: string;
23
+ value: Line;
24
+ };
@@ -0,0 +1,61 @@
1
+ export function getStatusFromComponent(component, daysEol) {
2
+ const { info } = component;
3
+ if (component.status) {
4
+ if (info.isEol && component.status && component.status !== 'EOL') {
5
+ throw new Error(`isEol is true but status is not EOL: ${component.purl}`);
6
+ }
7
+ return component.status;
8
+ }
9
+ // If API fails to set status, we derive it based on other properties
10
+ if (daysEol === null) {
11
+ return info.isEol ? 'EOL' : 'OK';
12
+ }
13
+ if (daysEol > 0) {
14
+ // daysEol is positive means we're past the EOL date
15
+ return 'EOL';
16
+ }
17
+ // daysEol is zero or negative means we haven't reached EOL yet
18
+ return 'LTS';
19
+ }
20
+ export function daysBetween(date1, date2) {
21
+ const msPerDay = 1000 * 60 * 60 * 24 + 15; // milliseconds in a day plus 15 ms
22
+ return Math.round((date2.getTime() - date1.getTime()) / msPerDay);
23
+ }
24
+ export function getDaysEolFromEolAt(eolAt) {
25
+ return eolAt ? Math.abs(daysBetween(new Date(), eolAt)) : null;
26
+ }
27
+ export function getMessageAndStatus(status, daysEol) {
28
+ let msg = '';
29
+ let stat = '';
30
+ const stringifiedDaysEol = daysEol ? daysEol.toString() : 'unknown';
31
+ switch (status) {
32
+ case 'EOL': {
33
+ stat = 'EOL';
34
+ msg = `EOL'd ${stringifiedDaysEol} days ago.`;
35
+ break;
36
+ }
37
+ case 'LTS': {
38
+ stat = 'LTS';
39
+ msg = `Will go EOL in ${stringifiedDaysEol} days.`;
40
+ break;
41
+ }
42
+ case 'OK': {
43
+ stat = 'OK';
44
+ break;
45
+ }
46
+ default:
47
+ throw new Error(`Unknown status: ${status}`);
48
+ }
49
+ return { stat, msg };
50
+ }
51
+ export function formatLine(l, idx, ctx) {
52
+ const { daysEol, purl, status } = l;
53
+ const { stat, msg } = getMessageAndStatus(status, daysEol);
54
+ const padlen = ctx.total.toString().length;
55
+ const rownum = `${idx + 1}`.padStart(padlen, ' ');
56
+ const name = purl.padEnd(ctx.longest, ' ');
57
+ return {
58
+ name: `${rownum}. [${stat}] ${name} | ${msg}`,
59
+ value: l,
60
+ };
61
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A simple logging construct when you
3
+ * don't have the command instance handy
4
+ */
5
+ export declare const log: {
6
+ info: (_message?: unknown, ...args: unknown[]) => void;
7
+ warn: (_message?: unknown, ...args: unknown[]) => void;
8
+ debug: (_message?: unknown, ...args: unknown[]) => void;
9
+ };
10
+ export declare const initOclifLog: (info: (message?: unknown, ...args: unknown[]) => void, warn: (message?: unknown, ...args: unknown[]) => void, debug: (message?: unknown, ...args: unknown[]) => void) => void;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * A simple logging construct when you
3
+ * don't have the command instance handy
4
+ */
5
+ export const log = {
6
+ info: (_message, ...args) => {
7
+ console.log('[default_log]', ...args);
8
+ },
9
+ warn: (_message, ...args) => {
10
+ console.warn('[default_warn]', ...args);
11
+ },
12
+ debug: (_message, ...args) => {
13
+ console.debug('[default_debug]', ...args);
14
+ },
15
+ };
16
+ export const initOclifLog = (info, warn, debug) => {
17
+ log.info = info;
18
+ log.warn = warn;
19
+ log.debug = debug;
20
+ };
@@ -0,0 +1,4 @@
1
+ import type { NesApolloClient } from '../../api/nes/nes.client.ts';
2
+ import type { ScanResponseReport, ScanResult } from '../../api/types/nes.types.ts';
3
+ export declare const buildScanResult: (scan: ScanResponseReport) => ScanResult;
4
+ export declare const SbomScanner: (client: NesApolloClient) => (purls: string[]) => Promise<ScanResult>;
@@ -0,0 +1,25 @@
1
+ import { M_SCAN } from "../../api/queries/nes/sbom.js";
2
+ import { log } from "../log.svc.js";
3
+ export const buildScanResult = (scan) => {
4
+ const components = new Map();
5
+ for (const c of scan.components) {
6
+ components.set(c.purl, c);
7
+ }
8
+ return {
9
+ components,
10
+ message: scan.message,
11
+ success: true,
12
+ };
13
+ };
14
+ export const SbomScanner = (client) => async (purls) => {
15
+ const input = { components: purls, type: 'SBOM' };
16
+ const res = await client.mutate(M_SCAN.gql, { input });
17
+ const scan = res.data?.insights?.scan?.eol;
18
+ if (!scan?.success) {
19
+ log.info('failed scan %o', scan || {});
20
+ log.warn('scan failed');
21
+ throw new Error('Failed to provide scan: ');
22
+ }
23
+ const result = buildScanResult(scan);
24
+ return result;
25
+ };
@@ -0,0 +1,17 @@
1
+ import type { Sbom } from './eol/cdx.svc.ts';
2
+ /**
3
+ * Formats a value for CSV output by wrapping it in quotes if it contains commas.
4
+ * This ensures that values containing commas aren't split into multiple columns
5
+ * when the CSV is opened in a spreadsheet application.
6
+ */
7
+ export declare function formatCsvValue(value: string): string;
8
+ /**
9
+ * Converts an array of PURLs into either CSV or JSON format.
10
+ * For CSV output, adds a header row with "purl" and formats values to preserve commas.
11
+ * For JSON output, returns a properly indented JSON string.
12
+ */
13
+ export declare function getPurlOutput(purls: string[], output: string): string;
14
+ /**
15
+ * Translate an SBOM to a list of purls for api request.
16
+ */
17
+ export declare function extractPurls(sbom: Sbom): Promise<string[]>;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Formats a value for CSV output by wrapping it in quotes if it contains commas.
3
+ * This ensures that values containing commas aren't split into multiple columns
4
+ * when the CSV is opened in a spreadsheet application.
5
+ */
6
+ export function formatCsvValue(value) {
7
+ // If the value contains a comma, wrap it in quotes to preserve it as a single cell
8
+ return value.includes(',') ? `"${value}"` : value;
9
+ }
10
+ /**
11
+ * Converts an array of PURLs into either CSV or JSON format.
12
+ * For CSV output, adds a header row with "purl" and formats values to preserve commas.
13
+ * For JSON output, returns a properly indented JSON string.
14
+ */
15
+ export function getPurlOutput(purls, output) {
16
+ switch (output) {
17
+ case 'csv':
18
+ return ['purl', ...purls].map(formatCsvValue).join('\n');
19
+ default:
20
+ return JSON.stringify(purls, null, 2);
21
+ }
22
+ }
23
+ /**
24
+ * Translate an SBOM to a list of purls for api request.
25
+ */
26
+ export async function extractPurls(sbom) {
27
+ const { components: comps } = sbom;
28
+ return comps.map((c) => c.purl) ?? [];
29
+ }
@@ -0,0 +1,3 @@
1
+ import type { Answers } from 'inquirer';
2
+ import { type Line } from '../service/line.svc.ts';
3
+ export declare function promptComponentDetails(lines: Line[]): Promise<Answers>;
@@ -0,0 +1,17 @@
1
+ import inquirer from 'inquirer';
2
+ import { formatLine } from "../service/line.svc.js";
3
+ export function promptComponentDetails(lines) {
4
+ const context = {
5
+ longest: lines.map((l) => l.purl.length).reduce((a, l) => Math.max(a, l), 0),
6
+ total: lines.length,
7
+ };
8
+ return inquirer.prompt([
9
+ {
10
+ choices: lines.map((l, idx) => formatLine(l, idx, context)),
11
+ message: 'Which components',
12
+ name: 'selected',
13
+ pageSize: 20,
14
+ type: 'checkbox',
15
+ },
16
+ ]);
17
+ }
package/package.json CHANGED
@@ -1,24 +1,81 @@
1
1
  {
2
2
  "name": "@herodevs/cli",
3
- "version": "0.3.1",
3
+ "version": "1.0.0-beta.1",
4
+ "author": "HeroDevs, Inc",
4
5
  "bin": {
5
- "hd": "./src/main.js",
6
- "hdcli": "./src/main.js"
6
+ "hd": "./bin/run.js"
7
7
  },
8
+ "type": "module",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/herodevs/cli"
12
+ },
13
+ "homepage": "https://github.com/herodevs/cli",
14
+ "bugs": "https://github.com/@herodevs/cli/issues",
15
+ "scripts": {
16
+ "build": "shx rm -rf dist && tsc -b",
17
+ "ci": "biome ci",
18
+ "ci:fix": "biome check --write",
19
+ "clean": "shx rm -rf dist && npm run clean:files && shx rm -rf node_modules",
20
+ "clean:files": "shx rm -f nes.**.csv nes.**.json nes.**.text",
21
+ "dev": "npm run build && ./bin/dev.js",
22
+ "format": "biome format --write",
23
+ "lint": "biome lint --write",
24
+ "postpack": "shx rm -f oclif.manifest.json",
25
+ "prepack": "oclif manifest && oclif readme",
26
+ "pretest": "npm run lint && npm run typecheck",
27
+ "readme": "npm run ci:fix && npm run build && npm exec oclif readme",
28
+ "test": "node --disable-warning=ExperimentalWarning --experimental-strip-types --test \"test/**/*.test.ts\"",
29
+ "typecheck": "tsc --noEmit",
30
+ "version": "oclif readme && git add README.md"
31
+ },
32
+ "keywords": [
33
+ "herodevs",
34
+ "cli",
35
+ "herodevs cli"
36
+ ],
8
37
  "dependencies": {
9
- "@apollo/client": "^3.10.1",
10
- "@inquirer/prompts": "^5.0.2",
11
- "date-fns": "^3.6.0",
12
- "git-last-commit": "^1.0.1",
38
+ "@apollo/client": "^3.13.1",
13
39
  "graphql": "^16.8.1",
14
- "isomorphic-fetch": "^3.0.0",
15
- "ora": "5.3.0",
16
- "sloc": "^0.3.2",
17
- "tslib": "^2.3.0",
18
- "yargs": "^17.7.2"
40
+ "inquirer": "^12.5.0",
41
+ "@oclif/core": "^4"
42
+ },
43
+ "devDependencies": {
44
+ "@biomejs/biome": "^1.8.3",
45
+ "@oclif/test": "^4",
46
+ "@types/inquirer": "^9.0.7",
47
+ "@types/node": "^22",
48
+ "@types/sinon": "^17.0.4",
49
+ "oclif": "^4",
50
+ "shx": "^0.3.3",
51
+ "sinon": "^19.0.2",
52
+ "typescript": "^5.8.0"
53
+ },
54
+ "engines": {
55
+ "node": ">=22.0.0"
56
+ },
57
+ "files": [
58
+ "./bin",
59
+ "./dist",
60
+ "LICENSE"
61
+ ],
62
+ "license": "MIT",
63
+ "main": "dist/index.js",
64
+ "oclif": {
65
+ "bin": "hd",
66
+ "dirname": "hd",
67
+ "commands": "./dist/commands",
68
+ "plugins": [
69
+ "@oclif/plugin-help",
70
+ "@oclif/plugin-plugins",
71
+ "@oclif/plugin-update"
72
+ ],
73
+ "topicSeparator": " ",
74
+ "update": {
75
+ "node": {
76
+ "version": ">=22.0.0"
77
+ }
78
+ }
19
79
  },
20
- "type": "commonjs",
21
- "main": "./src/main.js",
22
- "typings": "./src/main.d.ts",
23
- "types": "./src/main.d.ts"
80
+ "types": "dist/index.d.ts"
24
81
  }
@@ -1,11 +0,0 @@
1
- # core-types
2
-
3
- This library was generated with [Nx](https://nx.dev).
4
-
5
- ## Building
6
-
7
- Run `nx build core-types` to build the library.
8
-
9
- ## Running unit tests
10
-
11
- Run `nx test core-types` to execute the unit tests via [Jest](https://jestjs.io).
@@ -1,12 +0,0 @@
1
- {
2
- "name": "@herodevs/core-types",
3
- "version": "0.0.1",
4
- "dependencies": {
5
- "tslib": "^2.3.0"
6
- },
7
- "type": "commonjs",
8
- "main": "./src/index.js",
9
- "typings": "./src/index.d.ts",
10
- "private": true,
11
- "types": "./src/index.d.ts"
12
- }
@@ -1 +0,0 @@
1
- export * from './lib/project-type';
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./lib/project-type"), exports);
5
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/core-types/src/index.ts"],"names":[],"mappings":";;;AAAA,6DAAmC"}
@@ -1 +0,0 @@
1
- export type ProjectType = 'npm' | 'not configured';
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=project-type.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"project-type.js","sourceRoot":"","sources":["../../../../../libs/core-types/src/lib/project-type.ts"],"names":[],"mappings":""}
package/init/README.md DELETED
@@ -1,11 +0,0 @@
1
- # init
2
-
3
- This library was generated with [Nx](https://nx.dev).
4
-
5
- ## Building
6
-
7
- Run `nx build init` to build the library.
8
-
9
- ## Running unit tests
10
-
11
- Run `nx test init` to execute the unit tests via [Jest](https://jestjs.io).
package/init/package.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "name": "@herodevs/nes-init",
3
- "version": "0.0.1",
4
- "dependencies": {
5
- "@apollo/client": "^3.10.1",
6
- "@herodevs/core-types": "^0.0.1",
7
- "@herodevs/utility": "^0.0.1",
8
- "@inquirer/prompts": "^5.0.2",
9
- "ora": "^5.3.0",
10
- "tslib": "^2.3.0",
11
- "yargs": "^17.2.1"
12
- },
13
- "type": "commonjs",
14
- "main": "./src/index.js",
15
- "typings": "./src/index.d.ts",
16
- "private": true,
17
- "types": "./src/index.d.ts"
18
- }
@@ -1 +0,0 @@
1
- export * from './lib/init';
package/init/src/index.js DELETED
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./lib/init"), exports);
5
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/nes/init/src/index.ts"],"names":[],"mappings":";;;AAAA,qDAA2B"}
@@ -1,3 +0,0 @@
1
- import { ProjectType } from "../../../core-types/src";
2
- import { Entry } from './models';
3
- export declare function configureProject(accessToken: string, projectTypes: ProjectType[], packages: Entry[]): void;
@@ -1,10 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.configureProject = configureProject;
4
- const configure_npm_project_1 = require("./npm/configure-npm-project");
5
- function configureProject(accessToken, projectTypes, packages) {
6
- if (projectTypes.includes('npm')) {
7
- (0, configure_npm_project_1.configureNpmProject)(accessToken, packages);
8
- }
9
- }
10
- //# sourceMappingURL=configure-project.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"configure-project.js","sourceRoot":"","sources":["../../../../../../libs/nes/init/src/lib/configure-project.ts"],"names":[],"mappings":";;AAIA,4CAQC;AAXD,uEAAkE;AAGlE,SAAgB,gBAAgB,CAC9B,WAAmB,EACnB,YAA2B,EAC3B,QAAiB;IAEjB,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,IAAA,2CAAmB,EAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC"}
@@ -1,2 +0,0 @@
1
- import { Choice, Entry, ReleaseTrain } from './models';
2
- export declare function getPackageChoices(releaseTrain: ReleaseTrain): Choice<Entry>[];
@@ -1,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getPackageChoices = getPackageChoices;
4
- const utility_1 = require("../../../utility/src");
5
- function getPackageChoices(releaseTrain) {
6
- return releaseTrain.entries
7
- .map((e) => {
8
- var _a;
9
- return ({
10
- name: ((_a = e.packageVersion.origination) === null || _a === void 0 ? void 0 : _a.name) || e.packageVersion.name,
11
- value: e,
12
- });
13
- })
14
- .sort(utility_1.sortByName);
15
- }
16
- //# sourceMappingURL=get-package-choices.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"get-package-choices.js","sourceRoot":"","sources":["../../../../../../libs/nes/init/src/lib/get-package-choices.ts"],"names":[],"mappings":";;AAGA,8CAOC;AAVD,+CAA+C;AAG/C,SAAgB,iBAAiB,CAAC,YAA0B;IAC1D,OAAO,YAAY,CAAC,OAAO;SACxB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;;QAAC,OAAA,CAAC;YACX,IAAI,EAAE,CAAA,MAAA,CAAC,CAAC,cAAc,CAAC,WAAW,0CAAE,IAAI,KAAI,CAAC,CAAC,cAAc,CAAC,IAAI;YACjE,KAAK,EAAE,CAAC;SACT,CAAC,CAAA;KAAA,CAAC;SACF,IAAI,CAAC,oBAAU,CAAC,CAAC;AACtB,CAAC"}
@@ -1,2 +0,0 @@
1
- import { Choice, ReleaseTrain } from './models';
2
- export declare function getProductChoices(accessToken: string): Promise<Choice<ReleaseTrain[]>[]>;
@@ -1,29 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getProductChoices = getProductChoices;
4
- const tslib_1 = require("tslib");
5
- const utility_1 = require("../../../utility/src");
6
- const get_release_trains_1 = require("./get-release-trains");
7
- function getProductChoices(accessToken) {
8
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
9
- const releaseTrains = yield (0, get_release_trains_1.getReleaseTrains)(accessToken);
10
- const products = releaseTrains.reduce((acc, rt) => {
11
- rt.products.forEach((product) => {
12
- if (acc[product.name]) {
13
- acc[product.name].push(rt);
14
- }
15
- else {
16
- acc[product.name] = [rt];
17
- }
18
- });
19
- return acc;
20
- }, {});
21
- return Object.entries(products)
22
- .map(([key, value]) => ({
23
- name: key,
24
- value,
25
- }))
26
- .sort(utility_1.sortByName);
27
- });
28
- }
29
- //# sourceMappingURL=get-product-choices.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"get-product-choices.js","sourceRoot":"","sources":["../../../../../../libs/nes/init/src/lib/get-product-choices.ts"],"names":[],"mappings":";;AAIA,8CAqBC;;AAzBD,+CAA+C;AAE/C,6DAAwD;AAExD,SAAsB,iBAAiB,CAAC,WAAmB;;QACzD,MAAM,aAAa,GAAG,MAAM,IAAA,qCAAgB,EAAC,WAAW,CAAC,CAAC;QAE1D,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE;YAChD,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC9B,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;oBACtB,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC7B,CAAC;qBAAM,CAAC;oBACN,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAAuC,CAAC,CAAC;QAE5C,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;aAC5B,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;YACtB,IAAI,EAAE,GAAG;YACT,KAAK;SACN,CAAC,CAAC;aACF,IAAI,CAAC,oBAAU,CAAC,CAAC;IACtB,CAAC;CAAA"}
@@ -1,2 +0,0 @@
1
- import { ReleaseTrain } from './models';
2
- export declare function getReleaseTrains(accessToken: string): Promise<ReleaseTrain[]>;
@@ -1,57 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getReleaseTrains = getReleaseTrains;
4
- const tslib_1 = require("tslib");
5
- const core_1 = require("@apollo/client/core");
6
- function getReleaseTrains(accessToken) {
7
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
8
- var _a, _b, _c;
9
- const client = new core_1.ApolloClient({
10
- cache: new core_1.InMemoryCache(),
11
- uri: 'https://api.nes.herodevs.com/graphql',
12
- });
13
- try {
14
- const queryResult = yield client.query({
15
- query: (0, core_1.gql) `
16
- query RT($input: LicensingReleaseTrainsInput) {
17
- licensing {
18
- releaseTrains(input: $input) {
19
- results {
20
- key
21
- name
22
- products {
23
- id
24
- key
25
- name
26
- }
27
- entries {
28
- packageVersion {
29
- id
30
- name
31
- fqns
32
- origination {
33
- name
34
- type
35
- version
36
- }
37
- }
38
- }
39
- }
40
- }
41
- }
42
- }
43
- `,
44
- variables: { input: { tenantId: 1000, byToken: accessToken } },
45
- });
46
- const results = (_c = (_b = (_a = queryResult.data) === null || _a === void 0 ? void 0 : _a.licensing) === null || _b === void 0 ? void 0 : _b.releaseTrains) === null || _c === void 0 ? void 0 : _c.results;
47
- if (!results) {
48
- throw new Error(`Error getting release trains`);
49
- }
50
- return results;
51
- }
52
- catch (error) {
53
- throw new Error(`Error getting release trains`);
54
- }
55
- });
56
- }
57
- //# sourceMappingURL=get-release-trains.js.map