scanoss 0.37.0 → 0.38.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.
- package/CHANGELOG.md +11 -0
- package/build/main/cli/commands/dep.js +2 -2
- package/build/main/cli/commands/scan.js +2 -2
- package/build/main/sdk/Decompress/Decompressor/DecompressZips.js +17 -2
- package/build/main/sdk/Dependencies/DependencyScanner.d.ts +6 -1
- package/build/main/sdk/Dependencies/DependencyScanner.js +9 -4
- package/build/main/sdk/Dependencies/LocalDependency/DependencyTypes.d.ts +7 -1
- package/build/main/sdk/Dependencies/LocalDependency/LocalDependency.d.ts +4 -1
- package/build/main/sdk/Dependencies/LocalDependency/LocalDependency.js +9 -3
- package/build/main/sdk/Dependencies/LocalDependency/LocalDependency.spec.js +138 -1
- package/build/main/sdk/Dependencies/LocalDependency/parsers/buildGradleParser.d.ts +1 -1
- package/build/main/sdk/Dependencies/LocalDependency/parsers/buildGradleParser.js +59 -18
- package/build/main/sdk/Dependencies/LocalDependency/parsers/gradle/libsVersionsTomlParser.d.ts +27 -0
- package/build/main/sdk/Dependencies/LocalDependency/parsers/gradle/libsVersionsTomlParser.js +207 -0
- package/build/main/sdk/Dependencies/LocalDependency/parsers/parser.spec.js +158 -1
- package/build/main/tsconfig.tsbuildinfo +1 -1
- package/build/module/cli/commands/dep.js +2 -2
- package/build/module/cli/commands/scan.js +2 -2
- package/build/module/sdk/Decompress/Decompressor/DecompressZips.js +17 -2
- package/build/module/sdk/Dependencies/DependencyScanner.d.ts +6 -1
- package/build/module/sdk/Dependencies/DependencyScanner.js +9 -4
- package/build/module/sdk/Dependencies/LocalDependency/DependencyTypes.d.ts +7 -1
- package/build/module/sdk/Dependencies/LocalDependency/LocalDependency.d.ts +4 -1
- package/build/module/sdk/Dependencies/LocalDependency/LocalDependency.js +9 -3
- package/build/module/sdk/Dependencies/LocalDependency/LocalDependency.spec.js +102 -1
- package/build/module/sdk/Dependencies/LocalDependency/parsers/buildGradleParser.d.ts +1 -1
- package/build/module/sdk/Dependencies/LocalDependency/parsers/buildGradleParser.js +58 -17
- package/build/module/sdk/Dependencies/LocalDependency/parsers/gradle/libsVersionsTomlParser.d.ts +27 -0
- package/build/module/sdk/Dependencies/LocalDependency/parsers/gradle/libsVersionsTomlParser.js +199 -0
- package/build/module/sdk/Dependencies/LocalDependency/parsers/parser.spec.js +158 -1
- package/build/module/tsconfig.module.tsbuildinfo +1 -1
- package/package.json +3 -2
|
@@ -1,19 +1,49 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
2
3
|
import { PackageURL } from 'packageurl-js';
|
|
3
|
-
|
|
4
|
+
import { buildCatalogAliasMap } from './gradle/libsVersionsTomlParser';
|
|
5
|
+
const MANIFEST_FILES = ['build.gradle', 'build.gradle.kts'];
|
|
6
|
+
// Per-project cache of parsed version catalog (libs.versions.toml) entries.
|
|
7
|
+
// Outer key: project root directory path where gradle/libs.versions.toml was found
|
|
8
|
+
// Inner map: normalized alias (e.g. "androidx.activity.compose") → resolved Maven coordinates
|
|
9
|
+
// Example: { "/home/user/my-project" → { "hilt.android" → { purl: "pkg:maven/com.google.dagger/hilt-android", version: "2.59" } } }
|
|
10
|
+
const catalogCache = new Map();
|
|
4
11
|
const depBlockRex = /dependencies\s*{\s*(?<dependencies>(.|\n)*?)}/gm;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
function resolveCatalogAlias(line, catalogMap) {
|
|
13
|
+
const match = line.match(/\blibs\.([a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*)\b/);
|
|
14
|
+
if (match)
|
|
15
|
+
return catalogMap.get(match[1]);
|
|
16
|
+
}
|
|
17
|
+
function findCatalogMap(gradleFilePath, basePath) {
|
|
18
|
+
let dir = path.dirname(path.resolve(gradleFilePath));
|
|
19
|
+
const root = path.parse(dir).root;
|
|
20
|
+
// Stop at basePath (scan root) to avoid searching outside the project scope.
|
|
21
|
+
// Falls back to filesystem root when basePath is not provided.
|
|
22
|
+
const boundary = basePath ? path.resolve(basePath) : root;
|
|
23
|
+
while (true) {
|
|
24
|
+
if (catalogCache.has(dir))
|
|
25
|
+
return catalogCache.get(dir);
|
|
26
|
+
const tomlPath = path.join(dir, 'gradle', 'libs.versions.toml');
|
|
27
|
+
if (fs.existsSync(tomlPath)) {
|
|
28
|
+
const content = fs.readFileSync(tomlPath, 'utf8');
|
|
29
|
+
const map = buildCatalogAliasMap(content);
|
|
30
|
+
catalogCache.set(dir, map);
|
|
31
|
+
return map;
|
|
32
|
+
}
|
|
33
|
+
if (dir === boundary || dir === root)
|
|
34
|
+
break;
|
|
35
|
+
dir = path.dirname(dir);
|
|
36
|
+
}
|
|
37
|
+
return new Map();
|
|
38
|
+
}
|
|
39
|
+
export async function buildGradleParser(fileContent, filePath, basePath) {
|
|
12
40
|
// If the file is not a manifest file, return an empty results
|
|
13
41
|
const results = { file: filePath, purls: [] };
|
|
14
|
-
if (path.basename(filePath)
|
|
42
|
+
if (!MANIFEST_FILES.includes(path.basename(filePath)))
|
|
15
43
|
return results;
|
|
44
|
+
const catalogMap = findCatalogMap(filePath, basePath);
|
|
16
45
|
//For each dependency block, generate purls
|
|
46
|
+
depBlockRex.lastIndex = 0;
|
|
17
47
|
let gradle;
|
|
18
48
|
while ((gradle = depBlockRex.exec(fileContent)) !== null) {
|
|
19
49
|
let depBlock = gradle?.groups?.dependencies;
|
|
@@ -27,8 +57,8 @@ export async function buildGradleParser(fileContent, filePath) {
|
|
|
27
57
|
if (line == '')
|
|
28
58
|
continue;
|
|
29
59
|
current_config_name = getConfigNameFromLine(line);
|
|
30
|
-
//Multiline dependency
|
|
31
|
-
if (current_config_name && line.includes("(")) {
|
|
60
|
+
//Multiline dependency (only if line has '(' but not ')' on the same line)
|
|
61
|
+
if (current_config_name && line.includes("(") && !line.includes(")")) {
|
|
32
62
|
while (i < lines.length && !lines[i].includes(")")) {
|
|
33
63
|
const componentData = createPurlNameFromLine(lines[i]);
|
|
34
64
|
if (componentData != null) {
|
|
@@ -38,6 +68,12 @@ export async function buildGradleParser(fileContent, filePath) {
|
|
|
38
68
|
scope: current_config_name
|
|
39
69
|
});
|
|
40
70
|
}
|
|
71
|
+
else {
|
|
72
|
+
const entry = resolveCatalogAlias(lines[i], catalogMap);
|
|
73
|
+
if (entry) {
|
|
74
|
+
results.purls.push({ purl: entry.purl, requirement: entry.version, scope: current_config_name });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
41
77
|
i++;
|
|
42
78
|
}
|
|
43
79
|
current_config_name = '';
|
|
@@ -45,6 +81,11 @@ export async function buildGradleParser(fileContent, filePath) {
|
|
|
45
81
|
else { //Single line dependency
|
|
46
82
|
const componentData = createPurlNameFromLine(line);
|
|
47
83
|
if (componentData == null) {
|
|
84
|
+
// Try resolving via catalog alias
|
|
85
|
+
const entry = resolveCatalogAlias(line, catalogMap);
|
|
86
|
+
if (entry) {
|
|
87
|
+
results.purls.push({ purl: entry.purl, requirement: entry.version, scope: current_config_name });
|
|
88
|
+
}
|
|
48
89
|
current_config_name = '';
|
|
49
90
|
continue;
|
|
50
91
|
}
|
|
@@ -56,9 +97,9 @@ export async function buildGradleParser(fileContent, filePath) {
|
|
|
56
97
|
}
|
|
57
98
|
function getConfigNameFromLine(line) {
|
|
58
99
|
let configName = "";
|
|
59
|
-
const dep = line.split(
|
|
100
|
+
const dep = line.split(/[\s(]/);
|
|
60
101
|
if (dep.length)
|
|
61
|
-
configName = dep[0].
|
|
102
|
+
configName = dep[0].trim();
|
|
62
103
|
return configName;
|
|
63
104
|
}
|
|
64
105
|
function createPurlNameFromLine(line) {
|
|
@@ -73,9 +114,9 @@ function createPurlNameFromLine(line) {
|
|
|
73
114
|
version = dep.groups.version;
|
|
74
115
|
}
|
|
75
116
|
else if (line.includes("group") && line.includes("name") && line.includes("version")) {
|
|
76
|
-
version = line.match(/version
|
|
77
|
-
name = line.match(/name
|
|
78
|
-
namespace = line.match(/group
|
|
117
|
+
version = line.match(/version\s*[:=]\s*['"](?<version>[\w\.\-\d]+)['"]/)?.groups?.version;
|
|
118
|
+
name = line.match(/name\s*[:=]\s*['"](?<name>[\w\.\-\d]+)['"]/)?.groups?.name;
|
|
119
|
+
namespace = line.match(/group\s*[:=]\s*['"](?<group>[\w\.\-\d]+)['"]/)?.groups?.group;
|
|
79
120
|
}
|
|
80
121
|
let purlName = "";
|
|
81
122
|
if (name && namespace) {
|
|
@@ -84,4 +125,4 @@ function createPurlNameFromLine(line) {
|
|
|
84
125
|
}
|
|
85
126
|
return null;
|
|
86
127
|
}
|
|
87
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
128
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGRHcmFkbGVQYXJzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvc2RrL0RlcGVuZGVuY2llcy9Mb2NhbERlcGVuZGVuY3kvcGFyc2Vycy9idWlsZEdyYWRsZVBhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3BCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFpQixvQkFBb0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBR3RGLE1BQU0sY0FBYyxHQUFHLENBQUMsY0FBYyxFQUFFLGtCQUFrQixDQUFDLENBQUM7QUFDNUQsNEVBQTRFO0FBQzVFLG1GQUFtRjtBQUNuRiw4RkFBOEY7QUFDOUYsb0lBQW9JO0FBQ3BJLE1BQU0sWUFBWSxHQUFHLElBQUksR0FBRyxFQUFzQyxDQUFDO0FBQ25FLE1BQU0sV0FBVyxHQUFHLGlEQUFpRCxDQUFDO0FBR3RFLFNBQVMsbUJBQW1CLENBQUMsSUFBWSxFQUFFLFVBQXNDO0lBQy9FLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQztJQUN4RSxJQUFJLEtBQUs7UUFBRSxPQUFPLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDN0MsQ0FBQztBQUVELFNBQVMsY0FBYyxDQUFDLGNBQXNCLEVBQUUsUUFBaUI7SUFDL0QsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7SUFDckQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDbEMsNkVBQTZFO0lBQzdFLCtEQUEr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
|
package/build/module/sdk/Dependencies/LocalDependency/parsers/gradle/libsVersionsTomlParser.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ILocalDependency } from '../../DependencyTypes';
|
|
2
|
+
export interface ICatalogEntry {
|
|
3
|
+
purl: string;
|
|
4
|
+
version?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Normalizes a TOML alias key to match Gradle accessor notation.
|
|
8
|
+
* Replaces dashes and underscores with dots: "hilt-android" → "hilt.android"
|
|
9
|
+
*/
|
|
10
|
+
export declare function normalizeCatalogAlias(alias: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Builds a map from normalized catalog alias to resolved Maven coordinates.
|
|
13
|
+
* Keys use dot-separated notation matching Kotlin DSL accessors (e.g., "hilt.android").
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildCatalogAliasMap(fileContent: string): Map<string, ICatalogEntry>;
|
|
16
|
+
/**
|
|
17
|
+
* Parses a Gradle Version Catalog TOML file (libs.versions.toml) and extracts
|
|
18
|
+
* Maven dependency coordinates as PURLs.
|
|
19
|
+
*
|
|
20
|
+
* Supports:
|
|
21
|
+
* - module + version.ref: `lib = { module = "group:artifact", version.ref = "key" }`
|
|
22
|
+
* - module + inline version: `lib = { module = "group:artifact", version = "1.0" }`
|
|
23
|
+
* - group/name form: `lib = { group = "g", name = "n", version.ref = "key" }`
|
|
24
|
+
* - simple string: `lib = "group:artifact:version"`
|
|
25
|
+
* - no version (BOM-managed): `lib = { module = "group:artifact" }`
|
|
26
|
+
*/
|
|
27
|
+
export declare function libsVersionsTomlParser(fileContent: string, filePath: string): Promise<ILocalDependency>;
|
package/build/module/sdk/Dependencies/LocalDependency/parsers/gradle/libsVersionsTomlParser.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { PackageURL } from 'packageurl-js';
|
|
3
|
+
/**
|
|
4
|
+
* Known limitations:
|
|
5
|
+
* - Rich versions in [versions] (e.g. { strictly = "[4.0, 5.0[", prefer = "4.12.0" }) are not parsed.
|
|
6
|
+
* Only simple key = "value" entries are supported.
|
|
7
|
+
* - The version catalog is expected at gradle/libs.versions.toml (Gradle default convention).
|
|
8
|
+
* Custom catalog paths configured via settings.gradle.kts versionCatalogs block are not detected.
|
|
9
|
+
* - settings.gradle.kts is not parsed. Plugin declarations and catalog configuration in settings are ignored.
|
|
10
|
+
* - Multi-line library entries are not supported. Each library must be declared on a single line.
|
|
11
|
+
* e.g. `hilt-android = { module = "...", version.ref = "hilt" }` works, but splitting it
|
|
12
|
+
* across multiple lines does not.
|
|
13
|
+
*/
|
|
14
|
+
const MANIFEST_FILE = 'libs.versions.toml';
|
|
15
|
+
// --- Exported functions ---
|
|
16
|
+
/**
|
|
17
|
+
* Normalizes a TOML alias key to match Gradle accessor notation.
|
|
18
|
+
* Replaces dashes and underscores with dots: "hilt-android" → "hilt.android"
|
|
19
|
+
*/
|
|
20
|
+
export function normalizeCatalogAlias(alias) {
|
|
21
|
+
return alias.replace(/[-_]/g, '.');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Builds a map from normalized catalog alias to resolved Maven coordinates.
|
|
25
|
+
* Keys use dot-separated notation matching Kotlin DSL accessors (e.g., "hilt.android").
|
|
26
|
+
*/
|
|
27
|
+
export function buildCatalogAliasMap(fileContent) {
|
|
28
|
+
const map = new Map();
|
|
29
|
+
const versions = parseVersionsSection(fileContent);
|
|
30
|
+
const libraries = parseLibrariesSection(fileContent, versions);
|
|
31
|
+
for (const lib of libraries) {
|
|
32
|
+
if (lib.namespace && lib.name) {
|
|
33
|
+
const aliasKey = normalizeCatalogAlias(lib.alias);
|
|
34
|
+
const purlObj = new PackageURL('maven', lib.namespace, lib.name, undefined, undefined, undefined);
|
|
35
|
+
map.set(aliasKey, { purl: purlObj.toString(), version: lib.version });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return map;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parses a Gradle Version Catalog TOML file (libs.versions.toml) and extracts
|
|
42
|
+
* Maven dependency coordinates as PURLs.
|
|
43
|
+
*
|
|
44
|
+
* Supports:
|
|
45
|
+
* - module + version.ref: `lib = { module = "group:artifact", version.ref = "key" }`
|
|
46
|
+
* - module + inline version: `lib = { module = "group:artifact", version = "1.0" }`
|
|
47
|
+
* - group/name form: `lib = { group = "g", name = "n", version.ref = "key" }`
|
|
48
|
+
* - simple string: `lib = "group:artifact:version"`
|
|
49
|
+
* - no version (BOM-managed): `lib = { module = "group:artifact" }`
|
|
50
|
+
*/
|
|
51
|
+
export async function libsVersionsTomlParser(fileContent, filePath) {
|
|
52
|
+
const results = { file: filePath, purls: [] };
|
|
53
|
+
if (path.basename(filePath) !== MANIFEST_FILE)
|
|
54
|
+
return results;
|
|
55
|
+
const versions = parseVersionsSection(fileContent);
|
|
56
|
+
const libraries = parseLibrariesSection(fileContent, versions);
|
|
57
|
+
for (const lib of libraries) {
|
|
58
|
+
if (lib.namespace && lib.name) {
|
|
59
|
+
const purlObj = new PackageURL('maven', lib.namespace, lib.name, undefined, undefined, undefined);
|
|
60
|
+
results.purls.push({ purl: purlObj.toString(), ...(lib.version && { requirement: lib.version }) });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return results;
|
|
64
|
+
}
|
|
65
|
+
// --- Private helpers ---
|
|
66
|
+
/**
|
|
67
|
+
* Extracts the content of a TOML section by header name.
|
|
68
|
+
* Returns the text between `[sectionName]` and the next `[` header (or end of file).
|
|
69
|
+
*/
|
|
70
|
+
function extractSection(fileContent, sectionName) {
|
|
71
|
+
const regex = new RegExp(`^\\[${sectionName}\\]\\s*$`, 'm');
|
|
72
|
+
const match = regex.exec(fileContent);
|
|
73
|
+
if (!match)
|
|
74
|
+
return null;
|
|
75
|
+
const start = match.index + match[0].length;
|
|
76
|
+
const nextSection = fileContent.indexOf('\n[', start);
|
|
77
|
+
return nextSection === -1
|
|
78
|
+
? fileContent.substring(start)
|
|
79
|
+
: fileContent.substring(start, nextSection);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Parses the [versions] section into a map of key -> version string.
|
|
83
|
+
*
|
|
84
|
+
* Example input:
|
|
85
|
+
* [versions]
|
|
86
|
+
* hilt = "2.51.1"
|
|
87
|
+
* kotlin = "2.0.0"
|
|
88
|
+
*
|
|
89
|
+
* Returns: Map { "hilt" → "2.51.1", "kotlin" → "2.0.0" }
|
|
90
|
+
*/
|
|
91
|
+
function parseVersionsSection(fileContent) {
|
|
92
|
+
const versions = new Map();
|
|
93
|
+
const section = extractSection(fileContent, 'versions');
|
|
94
|
+
if (!section)
|
|
95
|
+
return versions;
|
|
96
|
+
for (const line of section.split(/\r?\n/)) {
|
|
97
|
+
const trimmed = line.trim();
|
|
98
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
99
|
+
continue;
|
|
100
|
+
// Match: key = "value" or key = 'value'
|
|
101
|
+
const match = trimmed.match(/^([\w-]+)\s*=\s*["']([^"']+)["']/);
|
|
102
|
+
if (match) {
|
|
103
|
+
versions.set(match[1], match[2]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return versions;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Parses the [libraries] section and resolves version references.
|
|
110
|
+
*
|
|
111
|
+
* Example input:
|
|
112
|
+
* [libraries]
|
|
113
|
+
* hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
|
|
114
|
+
* simple = "com.example:simple:1.0.0"
|
|
115
|
+
*
|
|
116
|
+
* Returns: [
|
|
117
|
+
* { alias: "hilt-android", namespace: "com.google.dagger", name: "hilt-android", version: "2.51.1" },
|
|
118
|
+
* { alias: "simple", namespace: "com.example", name: "simple", version: "1.0.0" }
|
|
119
|
+
* ]
|
|
120
|
+
*/
|
|
121
|
+
function parseLibrariesSection(fileContent, versions) {
|
|
122
|
+
const libraries = [];
|
|
123
|
+
const section = extractSection(fileContent, 'libraries');
|
|
124
|
+
if (!section)
|
|
125
|
+
return libraries;
|
|
126
|
+
for (const line of section.split(/\r?\n/)) {
|
|
127
|
+
const trimmed = line.trim();
|
|
128
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
129
|
+
continue;
|
|
130
|
+
// Match the key = value pattern
|
|
131
|
+
const kvMatch = trimmed.match(/^([\w-]+)\s*=\s*(.*)/);
|
|
132
|
+
if (!kvMatch)
|
|
133
|
+
continue;
|
|
134
|
+
const value = kvMatch[2].trim();
|
|
135
|
+
const entry = parseLibraryValue(value, versions);
|
|
136
|
+
if (entry)
|
|
137
|
+
libraries.push({ alias: kvMatch[1], ...entry });
|
|
138
|
+
}
|
|
139
|
+
return libraries;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Parses a single library value from the TOML file.
|
|
143
|
+
*/
|
|
144
|
+
function parseLibraryValue(value, versions) {
|
|
145
|
+
// Simple string notation: "group:artifact:version"
|
|
146
|
+
const stringMatch = value.match(/^["']([^"']+)["']/);
|
|
147
|
+
if (stringMatch) {
|
|
148
|
+
const strContent = stringMatch[1];
|
|
149
|
+
const parts = strContent.split(':');
|
|
150
|
+
if (parts.length >= 2) {
|
|
151
|
+
return {
|
|
152
|
+
namespace: parts[0],
|
|
153
|
+
name: parts[1],
|
|
154
|
+
...(parts[2] && { version: parts[2] }),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
// Inline table notation: { ... }
|
|
160
|
+
if (value.startsWith('{')) {
|
|
161
|
+
let namespace;
|
|
162
|
+
let name;
|
|
163
|
+
let version;
|
|
164
|
+
// Check for module = "group:artifact"
|
|
165
|
+
const moduleMatch = value.match(/module\s*=\s*["']([^"']+)["']/);
|
|
166
|
+
if (moduleMatch) {
|
|
167
|
+
const parts = moduleMatch[1].split(':');
|
|
168
|
+
if (parts.length >= 2) {
|
|
169
|
+
namespace = parts[0];
|
|
170
|
+
name = parts[1];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// Check for group = "...", name = "..."
|
|
175
|
+
const groupMatch = value.match(/group\s*=\s*["']([^"']+)["']/);
|
|
176
|
+
const nameMatch = value.match(/name\s*=\s*["']([^"']+)["']/);
|
|
177
|
+
if (groupMatch)
|
|
178
|
+
namespace = groupMatch[1];
|
|
179
|
+
if (nameMatch)
|
|
180
|
+
name = nameMatch[1];
|
|
181
|
+
}
|
|
182
|
+
// Resolve version: version.ref = "key" or version = "value"
|
|
183
|
+
const versionRefMatch = value.match(/version\.ref\s*=\s*["']([^"']+)["']/);
|
|
184
|
+
if (versionRefMatch) {
|
|
185
|
+
version = versions.get(versionRefMatch[1]);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
const versionMatch = value.match(/(?<![.\w])version\s*=\s*["']([^"']+)["']/);
|
|
189
|
+
if (versionMatch) {
|
|
190
|
+
version = versionMatch[1];
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (namespace && name) {
|
|
194
|
+
return { namespace, name, ...(version && { version }) };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlic1ZlcnNpb25zVG9tbFBhcnNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9zZGsvRGVwZW5kZW5jaWVzL0xvY2FsRGVwZW5kZW5jeS9wYXJzZXJzL2dyYWRsZS9saWJzVmVyc2lvbnNUb21sUGFyc2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTNDOzs7Ozs7Ozs7O0dBVUc7QUFFSCxNQUFNLGFBQWEsR0FBRyxvQkFBb0IsQ0FBQztBQWlCM0MsNkJBQTZCO0FBRTdCOzs7R0FHRztBQUNILE1BQU0sVUFBVSxxQkFBcUIsQ0FBQyxLQUFhO0lBQ2pELE9BQU8sS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDckMsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxXQUFtQjtJQUN0RCxNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsRUFBeUIsQ0FBQztJQUM3QyxNQUFNLFFBQVEsR0FBRyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNuRCxNQUFNLFNBQVMsR0FBRyxxQkFBcUIsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFFL0QsS0FBSyxNQUFNLEdBQUcsSUFBSSxTQUFTLEVBQUUsQ0FBQztRQUM1QixJQUFJLEdBQUcsQ0FBQyxTQUFTLElBQUksR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzlCLE1BQU0sUUFBUSxHQUFHLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNsRCxNQUFNLE9BQU8sR0FBRyxJQUFJLFVBQVUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVB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
|