@cyclonedx/cdxgen 11.4.4 → 11.6.0

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 (90) hide show
  1. package/README.md +68 -64
  2. package/bin/cdxgen.js +31 -9
  3. package/lib/cli/index.js +336 -99
  4. package/lib/evinser/evinser.js +3 -0
  5. package/lib/evinser/{evinser.test.js → evinser.poku.js} +51 -33
  6. package/lib/evinser/{swiftsem.test.js → swiftsem.poku.js} +46 -45
  7. package/lib/helpers/cbomutils.poku.js +8 -0
  8. package/lib/helpers/{display.test.js → display.poku.js} +2 -2
  9. package/lib/helpers/dotnetutils.js +132 -0
  10. package/lib/helpers/dotnetutils.poku.js +429 -0
  11. package/lib/helpers/envcontext.js +20 -18
  12. package/lib/helpers/{envcontext.test.js → envcontext.poku.js} +24 -24
  13. package/lib/helpers/logger.js +0 -2
  14. package/lib/helpers/{protobom.test.js → protobom.poku.js} +12 -10
  15. package/lib/helpers/utils.js +853 -88
  16. package/lib/helpers/{utils.test.js → utils.poku.js} +1999 -1349
  17. package/lib/helpers/validator.js +10 -0
  18. package/lib/managers/binary.js +89 -11
  19. package/lib/managers/docker.js +47 -37
  20. package/lib/managers/{docker.test.js → docker.poku.js} +70 -59
  21. package/lib/parsers/iri.js +504 -0
  22. package/lib/parsers/iri.poku.js +406 -0
  23. package/lib/server/server.js +130 -7
  24. package/lib/server/server.poku.js +387 -0
  25. package/lib/stages/postgen/{annotator.test.js → annotator.poku.js} +11 -14
  26. package/lib/stages/postgen/{postgen.test.js → postgen.poku.js} +15 -15
  27. package/package.json +34 -16
  28. package/types/cli/index.d.ts +295 -0
  29. package/types/cli/index.d.ts.map +1 -0
  30. package/types/evinser/scalasem.d.ts +6 -0
  31. package/types/evinser/scalasem.d.ts.map +1 -0
  32. package/types/evinser/swiftsem.d.ts +103 -0
  33. package/types/evinser/swiftsem.d.ts.map +1 -0
  34. package/types/helpers/analyzer.d.ts +5 -0
  35. package/types/helpers/analyzer.d.ts.map +1 -0
  36. package/types/helpers/cbomutils.d.ts +15 -0
  37. package/types/helpers/cbomutils.d.ts.map +1 -0
  38. package/types/helpers/db.d.ts +19 -0
  39. package/types/helpers/db.d.ts.map +1 -0
  40. package/types/helpers/display.d.ts +12 -0
  41. package/types/helpers/display.d.ts.map +1 -0
  42. package/types/helpers/dotnetutils.d.ts +45 -0
  43. package/types/helpers/dotnetutils.d.ts.map +1 -0
  44. package/types/helpers/envcontext.d.ts +264 -0
  45. package/types/helpers/envcontext.d.ts.map +1 -0
  46. package/types/helpers/logger.d.ts +12 -0
  47. package/types/helpers/logger.d.ts.map +1 -0
  48. package/types/helpers/protobom.d.ts +3 -0
  49. package/types/helpers/protobom.d.ts.map +1 -0
  50. package/types/helpers/utils.d.ts +1556 -0
  51. package/types/helpers/utils.d.ts.map +1 -0
  52. package/types/helpers/validator.d.ts +11 -0
  53. package/types/helpers/validator.d.ts.map +1 -0
  54. package/types/lib/cli/index.d.ts +8 -1
  55. package/types/lib/cli/index.d.ts.map +1 -1
  56. package/types/lib/evinser/evinser.d.ts +2 -1
  57. package/types/lib/helpers/dotnetutils.d.ts +45 -0
  58. package/types/lib/helpers/dotnetutils.d.ts.map +1 -0
  59. package/types/lib/helpers/envcontext.d.ts +3 -8
  60. package/types/lib/helpers/envcontext.d.ts.map +1 -1
  61. package/types/lib/helpers/logger.d.ts +0 -1
  62. package/types/lib/helpers/logger.d.ts.map +1 -1
  63. package/types/lib/helpers/utils.d.ts +68 -66
  64. package/types/lib/helpers/utils.d.ts.map +1 -1
  65. package/types/lib/helpers/validator.d.ts.map +1 -1
  66. package/types/lib/managers/binary.d.ts.map +1 -1
  67. package/types/lib/managers/docker.d.ts.map +1 -1
  68. package/types/lib/server/server.d.ts +22 -2
  69. package/types/lib/server/server.d.ts.map +1 -1
  70. package/types/managers/binary.d.ts +37 -0
  71. package/types/managers/binary.d.ts.map +1 -0
  72. package/types/managers/docker.d.ts +56 -0
  73. package/types/managers/docker.d.ts.map +1 -0
  74. package/types/managers/oci.d.ts +2 -0
  75. package/types/managers/oci.d.ts.map +1 -0
  76. package/types/managers/piptree.d.ts +2 -0
  77. package/types/managers/piptree.d.ts.map +1 -0
  78. package/types/parsers/iri.d.ts +72 -0
  79. package/types/parsers/iri.d.ts.map +1 -0
  80. package/types/server/server.d.ts +34 -0
  81. package/types/server/server.d.ts.map +1 -0
  82. package/types/stages/postgen/annotator.d.ts +27 -0
  83. package/types/stages/postgen/annotator.d.ts.map +1 -0
  84. package/types/stages/postgen/postgen.d.ts +51 -0
  85. package/types/stages/postgen/postgen.d.ts.map +1 -0
  86. package/types/stages/pregen/pregen.d.ts +59 -0
  87. package/types/stages/pregen/pregen.d.ts.map +1 -0
  88. package/jest.config.js +0 -7
  89. package/lib/helpers/cbomutils.test.js +0 -8
  90. package/lib/server/server.test.js +0 -126
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from "node:fs";
2
2
 
3
- import { expect, test } from "@jest/globals";
3
+ import { assert, it } from "poku";
4
4
 
5
5
  import {
6
6
  constructServiceName,
@@ -9,7 +9,7 @@ import {
9
9
  parseSemanticSlices,
10
10
  } from "./evinser.js";
11
11
 
12
- test("Service detection test", () => {
12
+ it("Service detection test", () => {
13
13
  const usageSlice = JSON.parse(
14
14
  readFileSync("./test/data/usages.json", { encoding: "utf-8" }),
15
15
  );
@@ -17,83 +17,97 @@ test("Service detection test", () => {
17
17
  const servicesMap = {};
18
18
  for (const slice of objectSlices) {
19
19
  detectServicesFromUsages("java", slice, servicesMap);
20
- expect(servicesMap).toBeDefined();
20
+ assert.ok(servicesMap);
21
21
  const serviceName = constructServiceName("java", slice);
22
- expect(serviceName).toBeDefined();
22
+ assert.ok(serviceName);
23
23
  }
24
24
  });
25
25
 
26
- test("extract endpoints test", () => {
27
- expect(
26
+ it("extract endpoints test", () => {
27
+ assert.deepStrictEqual(
28
28
  extractEndpoints("java", '@GetMapping(value = { "/", "/home" })'),
29
- ).toEqual(["/", "/home"]);
30
- expect(
29
+ ["/", "/home"],
30
+ );
31
+ assert.deepStrictEqual(
31
32
  extractEndpoints(
32
33
  "java",
33
34
  '@PostMapping(value = "/issue", consumes = MediaType.APPLICATION_XML_VALUE)',
34
35
  ),
35
- ).toEqual(["/issue"]);
36
- expect(extractEndpoints("java", '@GetMapping("/token")')).toEqual(["/token"]);
37
- expect(
36
+ ["/issue"],
37
+ );
38
+ assert.deepStrictEqual(extractEndpoints("java", '@GetMapping("/token")'), [
39
+ "/token",
40
+ ]);
41
+ assert.deepStrictEqual(
38
42
  extractEndpoints(
39
43
  "javascript",
40
44
  'router.use("/api/v2/users",userRoutes.routes(),userRoutes.allowedMethods())',
41
45
  ),
42
- ).toEqual(["/api/v2/users"]);
43
- expect(
46
+ ["/api/v2/users"],
47
+ );
48
+ assert.deepStrictEqual(
44
49
  extractEndpoints(
45
50
  "javascript",
46
51
  "app.use('/encryptionkeys', serveIndexMiddleware, serveIndex('encryptionkeys', { icons: true, view: 'details' }))",
47
52
  ),
48
- ).toEqual(["/encryptionkeys"]);
49
- expect(
53
+ ["/encryptionkeys"],
54
+ );
55
+ assert.deepStrictEqual(
50
56
  extractEndpoints(
51
57
  "javascript",
52
58
  "app.use(express.static(path.resolve('frontend/dist/frontend')))",
53
59
  ),
54
- ).toEqual(["frontend/dist/frontend"]);
55
- expect(
60
+ ["frontend/dist/frontend"],
61
+ );
62
+ assert.deepStrictEqual(
56
63
  extractEndpoints(
57
64
  "javascript",
58
65
  "app.use('/ftp(?!/quarantine)/:file', fileServer())",
59
66
  ),
60
- ).toEqual(["/ftp(?!/quarantine)/:file"]);
61
- expect(
67
+ ["/ftp(?!/quarantine)/:file"],
68
+ );
69
+ assert.deepStrictEqual(
62
70
  extractEndpoints(
63
71
  "javascript",
64
72
  "app.use('/rest/basket/:id', security.isAuthorized())",
65
73
  ),
66
- ).toEqual(["/rest/basket/:id"]);
67
- expect(
74
+ ["/rest/basket/:id"],
75
+ );
76
+ assert.deepStrictEqual(
68
77
  extractEndpoints(
69
78
  "javascript",
70
79
  "app.get(['/.well-known/security.txt', '/security.txt'], verify.accessControlChallenges())",
71
80
  ),
72
- ).toEqual(["/.well-known/security.txt", "/security.txt"]);
73
- expect(
81
+ ["/.well-known/security.txt", "/security.txt"],
82
+ );
83
+ assert.deepStrictEqual(
74
84
  extractEndpoints(
75
85
  "javascript",
76
86
  'router.post("/convert",async(ctx:Context):Promise<void>=>{constparameters=ctx.request.body;constbatchClient=newBatchClient({region:"us-west-1"});constcommand=newSubmitJobCommand({jobName:parameters?.jobName,jobQueue:"FOO-ARN",jobDefinition:"BAR-ARN",parameters,});try{constobjectsOutput=awaitbatchClient.send(command);ctx.response.body=objectsOutput;}catch(err){//Poorexceptionhandlingctx.response.body=err;}})',
77
87
  ),
78
- ).toEqual(["/convert"]);
79
- expect(
88
+ ["/convert"],
89
+ );
90
+ assert.deepStrictEqual(
80
91
  extractEndpoints(
81
92
  "java",
82
93
  '@RequestMapping(path = "/{name}", method = RequestMethod.GET)',
83
94
  ),
84
- ).toEqual(["/{name}"]);
85
- expect(
95
+ ["/{name}"],
96
+ );
97
+ assert.deepStrictEqual(
86
98
  extractEndpoints("java", "@RequestMapping(method = RequestMethod.POST)"),
87
- ).toEqual([]);
88
- expect(
99
+ [],
100
+ );
101
+ assert.deepStrictEqual(
89
102
  extractEndpoints(
90
103
  "java",
91
104
  '@RequestMapping(value = "/{accountName}", method = RequestMethod.GET)',
92
105
  ),
93
- ).toEqual(["/{accountName}"]);
106
+ ["/{accountName}"],
107
+ );
94
108
  });
95
109
 
96
- test("parseSemanticSlices", () => {
110
+ it("parseSemanticSlices", () => {
97
111
  const semanticsSlice = JSON.parse(
98
112
  readFileSync("./test/data/swiftsem/semantics.slices.json", {
99
113
  encoding: "utf-8",
@@ -104,6 +118,10 @@ test("parseSemanticSlices", () => {
104
118
  encoding: "utf-8",
105
119
  }),
106
120
  );
107
- const retMap = parseSemanticSlices(bomJson.components, semanticsSlice);
108
- expect(retMap).toBeDefined();
121
+ const retMap = parseSemanticSlices(
122
+ "swift",
123
+ bomJson.components,
124
+ semanticsSlice,
125
+ );
126
+ assert.ok(retMap);
109
127
  });
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from "node:fs";
2
2
 
3
- import { expect, test } from "@jest/globals";
3
+ import { assert, it } from "poku";
4
4
 
5
5
  import {
6
6
  extractCompilerParamsFromBuild,
@@ -11,19 +11,20 @@ import {
11
11
  parseStructure,
12
12
  } from "./swiftsem.js";
13
13
 
14
- test("extractCompilerParamsFromBuild test", () => {
14
+ it("extractCompilerParamsFromBuild test", () => {
15
15
  const paramsObj = extractCompilerParamsFromBuild(
16
16
  readFileSync("./test/data/swiftsem/swift-build-output1.txt", {
17
17
  encoding: "utf-8",
18
18
  }),
19
19
  );
20
- expect(paramsObj.params).toBeDefined();
21
- expect(paramsObj.compilerArgs).toEqual(
20
+ assert.ok(paramsObj.params);
21
+ assert.deepStrictEqual(
22
+ paramsObj.compilerArgs,
22
23
  "-sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk -F /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -F -Xcc -I /Volumes/Work/sandbox/HAKit/.build/x86_64-apple-macosx/debug/Modules -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib -L /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib",
23
24
  );
24
25
  });
25
26
 
26
- test("parseDumpPackage", () => {
27
+ it("parseDumpPackage", () => {
27
28
  const metadata = parseDumpPackage(
28
29
  JSON.parse(
29
30
  readFileSync("./test/data/swiftsem/swift-dump-package.json", {
@@ -31,8 +32,8 @@ test("parseDumpPackage", () => {
31
32
  }),
32
33
  ),
33
34
  );
34
- expect(metadata.rootModule).toEqual("HAKit");
35
- expect(metadata.dependencies).toEqual([
35
+ assert.deepStrictEqual(metadata.rootModule, "HAKit");
36
+ assert.deepStrictEqual(metadata.dependencies, [
36
37
  {
37
38
  dependsOn: ["Starscream"],
38
39
  ref: "HAKit",
@@ -52,11 +53,11 @@ test("parseDumpPackage", () => {
52
53
  ]);
53
54
  });
54
55
 
55
- test("collectBuildSymbols", () => {
56
+ it("collectBuildSymbols", () => {
56
57
  const metadata = parseOutputFileMap(
57
58
  "./test/data/swiftsem/output-file-map.json",
58
59
  );
59
- expect(metadata).toEqual({
60
+ assert.deepStrictEqual(metadata, {
60
61
  moduleName: "swiftsem",
61
62
  moduleSymbols: [
62
63
  "Compression",
@@ -84,7 +85,7 @@ test("collectBuildSymbols", () => {
84
85
  });
85
86
  });
86
87
 
87
- test("parseModuleInfo", () => {
88
+ it("parseModuleInfo", () => {
88
89
  let metadata = parseModuleInfo(
89
90
  JSON.parse(
90
91
  readFileSync("./test/data/swiftsem/swift-module-info2.json", {
@@ -92,11 +93,11 @@ test("parseModuleInfo", () => {
92
93
  }),
93
94
  ),
94
95
  );
95
- expect(metadata).toBeDefined();
96
- expect(metadata.classes.length).toEqual(13);
97
- expect(metadata.protocols.length).toEqual(25);
98
- expect(metadata.enums.length).toEqual(16);
99
- expect(metadata.importedModules).toEqual([
96
+ assert.ok(metadata);
97
+ assert.deepStrictEqual(metadata.classes.length, 13);
98
+ assert.deepStrictEqual(metadata.protocols.length, 25);
99
+ assert.deepStrictEqual(metadata.enums.length, 16);
100
+ assert.deepStrictEqual(metadata.importedModules, [
100
101
  "CommonCrypto",
101
102
  "Foundation",
102
103
  "Network",
@@ -113,11 +114,11 @@ test("parseModuleInfo", () => {
113
114
  }),
114
115
  ),
115
116
  );
116
- expect(metadata).toBeDefined();
117
- expect(metadata.classes.length).toEqual(8);
118
- expect(metadata.protocols.length).toEqual(14);
119
- expect(metadata.enums.length).toEqual(15);
120
- expect(metadata.importedModules).toEqual([
117
+ assert.ok(metadata);
118
+ assert.deepStrictEqual(metadata.classes.length, 8);
119
+ assert.deepStrictEqual(metadata.protocols.length, 14);
120
+ assert.deepStrictEqual(metadata.enums.length, 15);
121
+ assert.deepStrictEqual(metadata.importedModules, [
121
122
  "Dispatch",
122
123
  "Foundation",
123
124
  "Network",
@@ -129,7 +130,7 @@ test("parseModuleInfo", () => {
129
130
  ]);
130
131
  });
131
132
 
132
- test("parseStructure", () => {
133
+ it("parseStructure", () => {
133
134
  let metadata = parseStructure(
134
135
  JSON.parse(
135
136
  readFileSync("./test/data/swiftsem/swift-structure-starscream2.json", {
@@ -137,8 +138,8 @@ test("parseStructure", () => {
137
138
  }),
138
139
  ),
139
140
  );
140
- expect(metadata).toBeDefined();
141
- expect(metadata.referredTypes).toEqual([
141
+ assert.ok(metadata);
142
+ assert.deepStrictEqual(metadata.referredTypes, [
142
143
  "DispatchQueue",
143
144
  "Equatable",
144
145
  "HAData",
@@ -158,8 +159,8 @@ test("parseStructure", () => {
158
159
  }),
159
160
  ),
160
161
  );
161
- expect(metadata).toBeDefined();
162
- expect(metadata.referredTypes).toEqual([
162
+ assert.ok(metadata);
163
+ assert.deepStrictEqual(metadata.referredTypes, [
163
164
  "@escaping () -> Void",
164
165
  "@escaping (HACancellable, T) -> Void",
165
166
  "@escaping (Result<T, HAError>) -> Void",
@@ -202,8 +203,8 @@ test("parseStructure", () => {
202
203
  }),
203
204
  ),
204
205
  );
205
- expect(metadata).toBeDefined();
206
- expect(metadata.referredTypes).toEqual([
206
+ assert.ok(metadata);
207
+ assert.deepStrictEqual(metadata.referredTypes, [
207
208
  "AVSpeechSynthesizer",
208
209
  "AVSpeechSynthesizerDelegate",
209
210
  "AVSpeechUtterance",
@@ -216,8 +217,8 @@ test("parseStructure", () => {
216
217
  }),
217
218
  ),
218
219
  );
219
- expect(metadata).toBeDefined();
220
- expect(metadata.referredTypes).toEqual([
220
+ assert.ok(metadata);
221
+ assert.deepStrictEqual(metadata.referredTypes, [
221
222
  "(URL, URL) throws -> Void",
222
223
  "@escaping (GRDBWriteTransaction) throws -> Result<Void, Error>",
223
224
  "CaseIterable",
@@ -246,7 +247,7 @@ test("parseStructure", () => {
246
247
  ]);
247
248
  });
248
249
 
249
- test("parseIndex", () => {
250
+ it("parseIndex", () => {
250
251
  let metadata = parseIndex(
251
252
  JSON.parse(
252
253
  readFileSync("./test/data/swiftsem/swift-index-starscream.json", {
@@ -254,10 +255,10 @@ test("parseIndex", () => {
254
255
  }),
255
256
  ),
256
257
  );
257
- expect(metadata).toBeDefined();
258
- expect(metadata.obfuscatedSymbols).toBeDefined();
259
- expect(metadata.symbolLocations).toBeDefined();
260
- expect(metadata.swiftModules).toEqual([
258
+ assert.ok(metadata);
259
+ assert.ok(metadata.obfuscatedSymbols);
260
+ assert.ok(metadata.symbolLocations);
261
+ assert.deepStrictEqual(metadata.swiftModules, [
261
262
  "Combine",
262
263
  "CoreFoundation",
263
264
  "Darwin",
@@ -278,7 +279,7 @@ test("parseIndex", () => {
278
279
  "sys_time",
279
280
  "unistd",
280
281
  ]);
281
- expect(metadata.clangModules).toEqual([
282
+ assert.deepStrictEqual(metadata.clangModules, [
282
283
  "CoreFoundation",
283
284
  "Darwin",
284
285
  "Dispatch",
@@ -306,10 +307,10 @@ test("parseIndex", () => {
306
307
  }),
307
308
  ),
308
309
  );
309
- expect(metadata).toBeDefined();
310
- expect(metadata.obfuscatedSymbols).toBeDefined();
311
- expect(metadata.symbolLocations).toBeDefined();
312
- expect(metadata.swiftModules).toEqual([
310
+ assert.ok(metadata);
311
+ assert.ok(metadata.obfuscatedSymbols);
312
+ assert.ok(metadata.symbolLocations);
313
+ assert.deepStrictEqual(metadata.swiftModules, [
313
314
  "Combine",
314
315
  "CoreFoundation",
315
316
  "Darwin",
@@ -330,7 +331,7 @@ test("parseIndex", () => {
330
331
  "sys_time",
331
332
  "unistd",
332
333
  ]);
333
- expect(metadata.clangModules).toEqual([
334
+ assert.deepStrictEqual(metadata.clangModules, [
334
335
  "CoreFoundation",
335
336
  "Darwin",
336
337
  "Dispatch",
@@ -359,15 +360,15 @@ test("parseIndex", () => {
359
360
  }),
360
361
  ),
361
362
  );
362
- expect(metadata).toBeDefined();
363
- expect(metadata.obfuscatedSymbols).toBeDefined();
364
- expect(metadata.symbolLocations).toBeDefined();
365
- expect(metadata.swiftModules).toEqual([
363
+ assert.ok(metadata);
364
+ assert.ok(metadata.obfuscatedSymbols);
365
+ assert.ok(metadata.symbolLocations);
366
+ assert.deepStrictEqual(metadata.swiftModules, [
366
367
  "Swift",
367
368
  "_Concurrency",
368
369
  "_StringProcessing",
369
370
  ]);
370
- expect(metadata.clangModules).toEqual([
371
+ assert.deepStrictEqual(metadata.clangModules, [
371
372
  "AVFAudio",
372
373
  "SwiftShims",
373
374
  "_SwiftConcurrencyShims",
@@ -0,0 +1,8 @@
1
+ import { assert, it } from "poku";
2
+
3
+ import { collectOSCryptoLibs } from "./cbomutils.js";
4
+
5
+ it("cbom utils tests", () => {
6
+ const cryptoLibs = collectOSCryptoLibs();
7
+ assert.ok(cryptoLibs);
8
+ });
@@ -1,10 +1,10 @@
1
1
  import { readFileSync } from "node:fs";
2
2
 
3
- import { test } from "@jest/globals";
3
+ import { it } from "poku";
4
4
 
5
5
  import { printDependencyTree } from "./display.js";
6
6
 
7
- test("print tree test", () => {
7
+ it("print tree test", () => {
8
8
  const bomJson = JSON.parse(
9
9
  readFileSync("./test/data/vuln-spring-1.5.bom.json", { encoding: "utf-8" }),
10
10
  );
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Extracts version number from a HintPath in .NET project files
3
+ * @param {string|null|undefined} hintPath - The HintPath string to extract version from
4
+ * @returns {string|null} The extracted version number or null if not found
5
+ * @example
6
+ * extractVersionFromHintPath('..\\packages\\BouncyCastle.Cryptography.2.6.2\\lib\\net461\\BouncyCastle.Cryptography.dll')
7
+ * // returns '2.6.2'
8
+ *
9
+ * extractVersionFromHintPath('C:\\Users\\user\\.nuget\\packages\\microsoft.entityframeworkcore\\7.0.10\\lib\\net6.0\\Microsoft.EntityFrameworkCore.dll')
10
+ * // returns '7.0.10'
11
+ *
12
+ * extractVersionFromHintPath('../packages/MyLib.1.0.0+build.123/lib/net48/MyLib.dll')
13
+ * // returns '1.0.0+build.123'
14
+ */
15
+ export function extractVersionFromHintPath(hintPath) {
16
+ if (!hintPath || typeof hintPath !== "string") {
17
+ return null;
18
+ }
19
+
20
+ const normalizedPath = hintPath.replace(/\\/g, "/");
21
+
22
+ const directPackagePattern =
23
+ /(?:packages|nuget|\.nuget\/packages|paquets)\/([^\/]+?)\.(\d+(?:\.\d+){1,3}(?:-[a-zA-Z0-9.-]*)?(?:\+[a-zA-Z0-9.-]+)?)(?:\/|$)/i;
24
+ const directMatch = normalizedPath.match(directPackagePattern);
25
+ if (directMatch) {
26
+ return directMatch[2];
27
+ }
28
+
29
+ const structuredPattern =
30
+ /(?:^|\/)(?:packages|nuget|\.nuget\/packages|paquets)\/.+?\/(\d+(?:\.\d+){1,3}(?:-[a-zA-Z0-9.-]*)?(?:\+[a-zA-Z0-9.-]+)?)(?:\/|$)/i;
31
+ const structuredMatch = normalizedPath.match(structuredPattern);
32
+ if (structuredMatch) {
33
+ return structuredMatch[1];
34
+ }
35
+
36
+ const fallbackPatterns = [
37
+ /lib\/(\d+(?:\.\d+){1,3}(?:-[a-zA-Z0-9.-]*)?(?:\+[a-zA-Z0-9.-]+)?)\/[^\/]+\.dll$/,
38
+ /(?:^|\/)(\d+(?:\.\d+){1,3}(?:-[a-zA-Z0-9.-]*)?(?:\+[a-zA-Z0-9.-]+)?)(?:\/[^\/]*\.dll$)/,
39
+ ];
40
+
41
+ for (const pattern of fallbackPatterns) {
42
+ const fallbackMatch = normalizedPath.match(pattern);
43
+ if (fallbackMatch?.[1]) {
44
+ const version = fallbackMatch[1];
45
+ if (isValidVersion(version)) {
46
+ return version;
47
+ }
48
+ }
49
+ }
50
+
51
+ return null;
52
+ }
53
+
54
+ /**
55
+ * Validates if a string is a valid semantic version
56
+ * Supports versions with pre-release identifiers and build metadata
57
+ * @param {string|null|undefined} version - The version string to validate
58
+ * @returns {boolean} True if the version is valid, false otherwise
59
+ * @example
60
+ * isValidVersion('1.0.0') // true
61
+ * isValidVersion('1.0.0-alpha') // true
62
+ * isValidVersion('1.0.0+build.123') // true
63
+ * isValidVersion('1.0.0-alpha+build.123') // true
64
+ * isValidVersion('1.0.0-') // false
65
+ * isValidVersion('invalid') // false
66
+ */
67
+ export function isValidVersion(version) {
68
+ if (!version || typeof version !== "string") return false;
69
+
70
+ const versionRegex =
71
+ /^\d+(\.\d+){1,3}(-[a-zA-Z0-9]+(?:[.-][a-zA-Z0-9]+)*)?(\+[a-zA-Z0-9.-]+)?$/;
72
+ return versionRegex.test(version);
73
+ }
74
+
75
+ /**
76
+ * Extracts both package name and version from a HintPath in .NET project files
77
+ * @param {string|null|undefined} hintPath - The HintPath string to extract package info from
78
+ * @returns {{name: string|null, version: string|null}} Object containing package name and version
79
+ * @example
80
+ * extractPackageInfoFromHintPath('..\\packages\\BouncyCastle.Cryptography.2.6.2\\lib\\net461\\BouncyCastle.Cryptography.dll')
81
+ * // returns { name: 'BouncyCastle.Cryptography', version: '2.6.2' }
82
+ *
83
+ * extractPackageInfoFromHintPath('C:\\Users\\user\\.nuget\\packages\\microsoft.entityframeworkcore\\7.0.10\\lib\\net6.0\\Microsoft.EntityFrameworkCore.dll')
84
+ * // returns { name: 'microsoft.entityframeworkcore', version: '7.0.10' }
85
+ */
86
+ export function extractPackageInfoFromHintPath(hintPath) {
87
+ if (!hintPath || typeof hintPath !== "string") {
88
+ return { name: null, version: null };
89
+ }
90
+
91
+ const normalizedPath = hintPath.replace(/\\/g, "/");
92
+
93
+ const directPattern =
94
+ /(?:packages|nuget|\.nuget\/packages|paquets)\/([^\/]+?)\.(\d+(?:\.\d+){1,3}(?:-[a-zA-Z0-9.-]*)?(?:\+[a-zA-Z0-9.-]+)?)(?:\/|$)/i;
95
+ const directMatch = normalizedPath.match(directPattern);
96
+ if (directMatch) {
97
+ return {
98
+ name: directMatch[1],
99
+ version: directMatch[2],
100
+ };
101
+ }
102
+
103
+ const structuredPattern =
104
+ /(?:^|\/)(?:packages|nuget|\.nuget\/packages|paquets)\/(.+?)\/(\d+(?:\.\d+){1,3}(?:-[a-zA-Z0-9.-]*)?(?:\+[a-zA-Z0-9.-]+)?)(?:\/|$)/i;
105
+ const structuredMatch = normalizedPath.match(structuredPattern);
106
+ if (structuredMatch) {
107
+ const fullPath = structuredMatch[1];
108
+ const pathParts = fullPath.split("/").filter((part) => part);
109
+ const name = pathParts.length > 0 ? pathParts[pathParts.length - 1] : null;
110
+ return {
111
+ name: name,
112
+ version: structuredMatch[2],
113
+ };
114
+ }
115
+
116
+ const libPattern =
117
+ /lib\/(\d+(?:\.\d+){1,3}(?:-[a-zA-Z0-9.-]*)?(?:\+[a-zA-Z0-9.-]+)?)\/[^\/]+\.dll$/;
118
+ const libMatch = normalizedPath.match(libPattern);
119
+ if (libMatch?.[1]) {
120
+ const dllMatch = normalizedPath.match(/\/([^\/]+)\.dll$/);
121
+ return {
122
+ name: dllMatch ? dllMatch[1] : null,
123
+ version: libMatch[1],
124
+ };
125
+ }
126
+
127
+ const version = extractVersionFromHintPath(hintPath);
128
+ return {
129
+ name: null,
130
+ version: version,
131
+ };
132
+ }