kirograph 1.2.1 → 1.2.2
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/dist/bin/kirograph.js
CHANGED
|
@@ -128,7 +128,7 @@ process.on("uncaughtException", (err) => {
|
|
|
128
128
|
process.exit(1);
|
|
129
129
|
});
|
|
130
130
|
const program = new import_commander.Command();
|
|
131
|
-
program.name("kirograph").description("Semantic code knowledge graph for Kiro").version("1.2.
|
|
131
|
+
program.name("kirograph").description("Semantic code knowledge graph for Kiro").version("1.2.2").addHelpCommand(true).hook("preAction", (thisCommand) => {
|
|
132
132
|
const name = thisCommand.name();
|
|
133
133
|
if (name === "init") (0, import_banner.printBanner)();
|
|
134
134
|
});
|
|
@@ -178,15 +178,34 @@ function parseMavenDependencyTree(content) {
|
|
|
178
178
|
}
|
|
179
179
|
return result;
|
|
180
180
|
}
|
|
181
|
-
function
|
|
181
|
+
function extractMavenLicenseNames(content) {
|
|
182
182
|
const licensesMatch = content.match(/<licenses\b[^>]*>([\s\S]*?)<\/licenses>/i);
|
|
183
|
-
if (!licensesMatch) return
|
|
183
|
+
if (!licensesMatch) return [];
|
|
184
184
|
const licenseBlock = licensesMatch[1];
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
const names = [];
|
|
186
|
+
const licenseEntryRegex = /<license\b[^>]*>([\s\S]*?)<\/license>/gi;
|
|
187
|
+
let entryMatch;
|
|
188
|
+
while ((entryMatch = licenseEntryRegex.exec(licenseBlock)) !== null) {
|
|
189
|
+
const nameMatch = entryMatch[1].match(/<name>([^<]+)<\/name>/i);
|
|
190
|
+
if (nameMatch && nameMatch[1].trim() !== "") {
|
|
191
|
+
names.push(nameMatch[1].trim());
|
|
192
|
+
}
|
|
188
193
|
}
|
|
189
|
-
return
|
|
194
|
+
return names;
|
|
195
|
+
}
|
|
196
|
+
function extractMavenLicense(content) {
|
|
197
|
+
const names = extractMavenLicenseNames(content);
|
|
198
|
+
return names.length > 0 ? names.join(" OR ") : void 0;
|
|
199
|
+
}
|
|
200
|
+
function extractMavenParentCoords(content) {
|
|
201
|
+
const parentMatch = content.match(/<parent\b[^>]*>([\s\S]*?)<\/parent>/i);
|
|
202
|
+
if (!parentMatch) return void 0;
|
|
203
|
+
const block = parentMatch[1];
|
|
204
|
+
const groupId = extractXmlElement(block, "groupId");
|
|
205
|
+
const artifactId = extractXmlElement(block, "artifactId");
|
|
206
|
+
const version = extractXmlElement(block, "version");
|
|
207
|
+
if (!groupId || !artifactId || !version) return void 0;
|
|
208
|
+
return { groupId, artifactId, version };
|
|
190
209
|
}
|
|
191
210
|
function resolveMavenLocalRepoRoot() {
|
|
192
211
|
const settingsPath = path.join(os.homedir(), ".m2", "settings.xml");
|
|
@@ -198,14 +217,22 @@ function resolveMavenLocalRepoRoot() {
|
|
|
198
217
|
}
|
|
199
218
|
return path.join(os.homedir(), ".m2", "repository");
|
|
200
219
|
}
|
|
220
|
+
const MAX_MAVEN_PARENT_DEPTH = 10;
|
|
201
221
|
function findLocalMavenPomLicense(repoRoot, groupId, artifactId, version) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
222
|
+
let coords = { groupId, artifactId, version };
|
|
223
|
+
for (let depth = 0; coords && depth < MAX_MAVEN_PARENT_DEPTH; depth++) {
|
|
224
|
+
const pomPath = path.join(repoRoot, ...coords.groupId.split("."), coords.artifactId, coords.version, `${coords.artifactId}-${coords.version}.pom`);
|
|
225
|
+
let content;
|
|
226
|
+
try {
|
|
227
|
+
content = fs.readFileSync(pomPath, "utf8");
|
|
228
|
+
} catch {
|
|
229
|
+
return void 0;
|
|
230
|
+
}
|
|
231
|
+
const license = extractMavenLicense(content);
|
|
232
|
+
if (license !== void 0) return license;
|
|
233
|
+
coords = extractMavenParentCoords(content);
|
|
208
234
|
}
|
|
235
|
+
return void 0;
|
|
209
236
|
}
|
|
210
237
|
function applyLocalMavenLicenses(dependencies) {
|
|
211
238
|
const repoRoot = resolveMavenLocalRepoRoot();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/security/manifest/plugins/maven.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Maven Version Extraction Plugin for KiroGraph-Sec\n *\n * Extends the existing architecture maven parser to extract version constraints,\n * dependency scopes, and groupId/artifactId for security analysis.\n *\n * Reuses `mavenParser` from `src/architecture/manifest/maven.ts` for discovery and\n * basic parsing, then layers on version/scope extraction from pom.xml.\n */\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport type { ParsedDependency } from '../../types';\nimport { logWarn } from '../../../errors';\n\n/**\n * Maven scope to ParsedDependency scope mapping.\n *\n * - compile (default), runtime \u2192 production\n * - test \u2192 development\n * - provided, system \u2192 optional\n */\nfunction mapMavenScope(mavenScope: string | undefined): ParsedDependency['scope'] {\n if (!mavenScope || mavenScope.trim() === '') {\n return 'production';\n }\n\n const normalized = mavenScope.trim().toLowerCase();\n switch (normalized) {\n case 'compile':\n case 'runtime':\n return 'production';\n case 'test':\n return 'development';\n case 'provided':\n case 'system':\n return 'optional';\n default:\n // Unknown scope defaults to production\n return 'production';\n }\n}\n\n/**\n * Extract text content from an XML element by tag name within a given XML fragment.\n * Returns undefined if the element is not found.\n */\nfunction extractXmlElement(xml: string, tagName: string): string | undefined {\n const regex = new RegExp(`<${tagName}>([^<]*)</${tagName}>`);\n const match = xml.match(regex);\n return match ? match[1].trim() : undefined;\n}\n\n/**\n * Parse a Maven pom.xml manifest and extract dependency declarations\n * with groupId, artifactId, version constraints, and scopes.\n *\n * @param manifestPath - Absolute path to the pom.xml file\n * @param projectRoot - Absolute path to the project root directory\n * @returns Array of parsed dependencies with version and scope information\n */\nexport async function parseMavenManifest(\n manifestPath: string,\n projectRoot: string,\n): Promise<ParsedDependency[]> {\n const relativeManifest = path.relative(projectRoot, manifestPath).replace(/\\\\/g, '/');\n\n // Read the pom.xml content\n let content: string;\n try {\n content = fs.readFileSync(manifestPath, 'utf8');\n } catch (err) {\n logWarn(`[sec:maven] Failed to read ${relativeManifest}: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n\n // Validate basic XML structure\n if (!content.includes('<project')) {\n logWarn(`[sec:maven] Invalid pom.xml structure at ${relativeManifest} \u2014 missing <project> element`);\n return [];\n }\n\n // Extract all <dependency> blocks from the <dependencies> sections\n const dependencies: ParsedDependency[] = [];\n\n // <dependencyManagement> entries (BOM imports, version overrides for child\n // modules) are not themselves project dependencies \u2014 strip that block before\n // scanning so they don't get misread as declared dependencies.\n const dependenciesOnlyContent = content.replace(/<dependencyManagement>[\\s\\S]*?<\\/dependencyManagement>/g, '');\n\n // Match all <dependency>...</dependency> blocks\n const dependencyBlocks = dependenciesOnlyContent.matchAll(/<dependency>([\\s\\S]*?)<\\/dependency>/g);\n\n for (const block of dependencyBlocks) {\n const depXml = block[1];\n\n const groupId = extractXmlElement(depXml, 'groupId');\n const artifactId = extractXmlElement(depXml, 'artifactId');\n const version = extractXmlElement(depXml, 'version');\n const scope = extractXmlElement(depXml, 'scope');\n\n // Validate required fields\n if (!groupId || groupId.trim() === '') {\n logWarn(`[sec:maven] Missing groupId in dependency at ${relativeManifest} \u2014 skipping`);\n continue;\n }\n\n if (!artifactId || artifactId.trim() === '') {\n logWarn(`[sec:maven] Missing artifactId in dependency at ${relativeManifest} \u2014 skipping`);\n continue;\n }\n\n // Skip dependencies with unresolved Maven properties (e.g. ${project.version})\n if (groupId.includes('${') || artifactId.includes('${')) {\n logWarn(`[sec:maven] Unresolved property in dependency ${groupId}:${artifactId} at ${relativeManifest} \u2014 skipping`);\n continue;\n }\n\n // Build the dependency name as groupId:artifactId (Maven convention)\n const name = `${groupId}:${artifactId}`;\n\n // Version constraint \u2014 may be absent (managed by parent POM or BOM)\n let declaredConstraint: string;\n if (version && version.trim() !== '' && !version.includes('${')) {\n declaredConstraint = version.trim();\n } else {\n // No version or unresolved property \u2014 use empty string to indicate managed externally\n declaredConstraint = version && !version.includes('${') ? version.trim() : '';\n }\n\n const mappedScope = mapMavenScope(scope);\n\n dependencies.push({\n name,\n declaredConstraint,\n resolvedVersion: declaredConstraint || undefined,\n scope: mappedScope,\n ecosystem: 'maven',\n sourceManifest: relativeManifest,\n });\n }\n\n // Maven has no lock file, so a <dependency> with no explicit <version> (the\n // common case under a BOM parent like spring-boot-starter-parent) never gets\n // a resolvedVersion above, and packages pulled in only transitively (e.g.\n // tomcat-embed-core via spring-boot-starter-web) never appear in pom.xml at\n // all. If the project has a pre-generated `mvn dependency:tree` text file\n // (the closest Maven equivalent of a lock file), use it to fill in resolved\n // versions and capture transitive-only packages, mirroring how the npm\n // plugin layers package-lock.json on top of package.json.\n const manifestDir = path.dirname(manifestPath);\n const treeFile = findMavenDependencyTreeFile(manifestDir);\n\n if (treeFile) {\n const treeRelativePath = path.relative(projectRoot, treeFile.path).replace(/\\\\/g, '/');\n let treeContent: string;\n try {\n treeContent = fs.readFileSync(treeFile.path, 'utf8');\n } catch (err) {\n logWarn(`[sec:maven] Failed to read ${treeRelativePath}: ${err instanceof Error ? err.message : String(err)}`);\n applyLocalMavenLicenses(dependencies);\n return dependencies;\n }\n\n const treeEntries = parseMavenDependencyTree(treeContent);\n\n for (const dep of dependencies) {\n if (dep.resolvedVersion) continue;\n const treeEntry = treeEntries.get(dep.name);\n if (treeEntry) {\n dep.resolvedVersion = treeEntry.version;\n }\n }\n\n const directNames = new Set(dependencies.map(d => d.name));\n for (const [name, entry] of treeEntries) {\n if (directNames.has(name)) continue;\n dependencies.push({\n name,\n // No declared range exists at the project level for a transitive\n // package \u2014 the resolved version from the tree is the only constraint we have.\n declaredConstraint: entry.version,\n resolvedVersion: entry.version,\n scope: mapMavenScope(entry.scope),\n ecosystem: 'maven',\n sourceManifest: treeRelativePath,\n });\n }\n }\n\n applyLocalMavenLicenses(dependencies);\n return dependencies;\n}\n\n/**\n * Look for a pre-generated Maven dependency-tree text file next to pom.xml,\n * e.g. produced with:\n * mvn dependency:tree -DoutputFile=dependency-tree.txt\n * Checked locations, in order: `dependency-tree.txt` next to pom.xml, then\n * `target/dependency-tree.txt` (Maven's default build output directory).\n */\nfunction findMavenDependencyTreeFile(manifestDir: string): { path: string } | undefined {\n const candidates = ['dependency-tree.txt', path.join('target', 'dependency-tree.txt')];\n for (const candidate of candidates) {\n const candidatePath = path.join(manifestDir, candidate);\n if (fs.existsSync(candidatePath)) {\n return { path: candidatePath };\n }\n }\n return undefined;\n}\n\n/**\n * Parse `mvn dependency:tree` text output into a map of `groupId:artifactId`\n * to its resolved version and scope.\n *\n * Handles both:\n * groupId:artifactId:type:version:scope\n * groupId:artifactId:type:classifier:version:scope\n *\n * Skips the root project line (no scope segment) and parenthesized entries\n * like `(commons-logging:commons-logging:jar:1.1.1:compile - omitted for conflict with 1.2)`\n * \u2014 Maven's conflict resolution means only the winning version ends up on the\n * classpath, so omitted entries aren't actually present in the build.\n */\nexport function parseMavenDependencyTree(content: string): Map<string, { version: string; scope: string }> {\n const result = new Map<string, { version: string; scope: string }>();\n\n for (const rawLine of content.split(/\\r?\\n/)) {\n if (!rawLine.trim()) continue;\n\n // Strip Maven's ASCII tree-drawing prefix (e.g. \"| +- \", \" \\- \")\n const stripped = rawLine.replace(/^[\\s|+\\\\-]+/, '').trim();\n if (!stripped || stripped.startsWith('(')) continue;\n\n const parts = stripped.split(':');\n if (parts.length < 5) continue; // root project line (\"groupId:artifactId:version\") or malformed\n\n const groupId = parts[0];\n const artifactId = parts[1];\n const version = parts[parts.length - 2];\n const scope = parts[parts.length - 1];\n if (!groupId || !artifactId || !version) continue;\n\n const name = `${groupId}:${artifactId}`;\n if (!result.has(name)) {\n result.set(name, { version, scope });\n }\n }\n\n return result;\n}\n\n/**\n * Extract the first license name from a pom.xml `<licenses>` block.\n * Looks for: <licenses><license><name>...</name></license></licenses>\n * Works on any pom.xml content \u2014 the project's own, or a dependency's own\n * POM read from the local Maven repository.\n */\nfunction extractMavenLicense(content: string): string | undefined {\n const licensesMatch = content.match(/<licenses\\b[^>]*>([\\s\\S]*?)<\\/licenses>/i);\n if (!licensesMatch) return undefined;\n const licenseBlock = licensesMatch[1];\n const nameMatch = licenseBlock.match(/<name>([^<]+)<\\/name>/i);\n if (nameMatch && nameMatch[1].trim() !== '') {\n return nameMatch[1].trim();\n }\n return undefined;\n}\n\n/**\n * Resolve the local Maven repository root: `~/.m2/settings.xml`'s\n * `<localRepository>` override if set, else the conventional `~/.m2/repository`.\n */\nfunction resolveMavenLocalRepoRoot(): string {\n const settingsPath = path.join(os.homedir(), '.m2', 'settings.xml');\n try {\n const settings = fs.readFileSync(settingsPath, 'utf8');\n const match = settings.match(/<localRepository>([^<]+)<\\/localRepository>/i);\n if (match && match[1].trim() !== '') return match[1].trim();\n } catch {\n // No settings.xml, or unreadable \u2014 fall through to the default.\n }\n return path.join(os.homedir(), '.m2', 'repository');\n}\n\n/**\n * Each dependency's own license lives in its own POM, not the consuming\n * project's \u2014 Maven has no lock file to carry that data, but a dependency\n * that has ever been built or downloaded locally has its POM cached at the\n * standard local-repository layout:\n * <repoRoot>/<groupId with . -> />/<artifactId>/<version>/<artifactId>-<version>.pom\n * Local file only, no network call. Returns undefined when the dependency\n * has never been resolved locally (e.g. CI running from a clean cache), same\n * as before this fix \u2014 this fills in real data on top of an \"unknown\" default,\n * it never invents one.\n */\nfunction findLocalMavenPomLicense(repoRoot: string, groupId: string, artifactId: string, version: string): string | undefined {\n const pomPath = path.join(repoRoot, ...groupId.split('.'), artifactId, version, `${artifactId}-${version}.pom`);\n try {\n const content = fs.readFileSync(pomPath, 'utf8');\n return extractMavenLicense(content);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Fill in `license` for every dependency that has a resolved version, by\n * reading that exact groupId:artifactId:version's own POM from the local\n * Maven repository. Mutates `dependencies` in place.\n */\nfunction applyLocalMavenLicenses(dependencies: ParsedDependency[]): void {\n const repoRoot = resolveMavenLocalRepoRoot();\n for (const dep of dependencies) {\n if (!dep.resolvedVersion) continue;\n const [groupId, artifactId] = dep.name.split(':');\n if (!groupId || !artifactId) continue;\n const license = findLocalMavenPomLicense(repoRoot, groupId, artifactId, dep.resolvedVersion);\n if (license !== undefined) dep.license = license;\n }\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/**\n * Maven Version Extraction Plugin for KiroGraph-Sec\n *\n * Extends the existing architecture maven parser to extract version constraints,\n * dependency scopes, and groupId/artifactId for security analysis.\n *\n * Reuses `mavenParser` from `src/architecture/manifest/maven.ts` for discovery and\n * basic parsing, then layers on version/scope extraction from pom.xml.\n */\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport type { ParsedDependency } from '../../types';\nimport { logWarn } from '../../../errors';\n\n/**\n * Maven scope to ParsedDependency scope mapping.\n *\n * - compile (default), runtime \u2192 production\n * - test \u2192 development\n * - provided, system \u2192 optional\n */\nfunction mapMavenScope(mavenScope: string | undefined): ParsedDependency['scope'] {\n if (!mavenScope || mavenScope.trim() === '') {\n return 'production';\n }\n\n const normalized = mavenScope.trim().toLowerCase();\n switch (normalized) {\n case 'compile':\n case 'runtime':\n return 'production';\n case 'test':\n return 'development';\n case 'provided':\n case 'system':\n return 'optional';\n default:\n // Unknown scope defaults to production\n return 'production';\n }\n}\n\n/**\n * Extract text content from an XML element by tag name within a given XML fragment.\n * Returns undefined if the element is not found.\n */\nfunction extractXmlElement(xml: string, tagName: string): string | undefined {\n const regex = new RegExp(`<${tagName}>([^<]*)</${tagName}>`);\n const match = xml.match(regex);\n return match ? match[1].trim() : undefined;\n}\n\n/**\n * Parse a Maven pom.xml manifest and extract dependency declarations\n * with groupId, artifactId, version constraints, and scopes.\n *\n * @param manifestPath - Absolute path to the pom.xml file\n * @param projectRoot - Absolute path to the project root directory\n * @returns Array of parsed dependencies with version and scope information\n */\nexport async function parseMavenManifest(\n manifestPath: string,\n projectRoot: string,\n): Promise<ParsedDependency[]> {\n const relativeManifest = path.relative(projectRoot, manifestPath).replace(/\\\\/g, '/');\n\n // Read the pom.xml content\n let content: string;\n try {\n content = fs.readFileSync(manifestPath, 'utf8');\n } catch (err) {\n logWarn(`[sec:maven] Failed to read ${relativeManifest}: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n\n // Validate basic XML structure\n if (!content.includes('<project')) {\n logWarn(`[sec:maven] Invalid pom.xml structure at ${relativeManifest} \u2014 missing <project> element`);\n return [];\n }\n\n // Extract all <dependency> blocks from the <dependencies> sections\n const dependencies: ParsedDependency[] = [];\n\n // <dependencyManagement> entries (BOM imports, version overrides for child\n // modules) are not themselves project dependencies \u2014 strip that block before\n // scanning so they don't get misread as declared dependencies.\n const dependenciesOnlyContent = content.replace(/<dependencyManagement>[\\s\\S]*?<\\/dependencyManagement>/g, '');\n\n // Match all <dependency>...</dependency> blocks\n const dependencyBlocks = dependenciesOnlyContent.matchAll(/<dependency>([\\s\\S]*?)<\\/dependency>/g);\n\n for (const block of dependencyBlocks) {\n const depXml = block[1];\n\n const groupId = extractXmlElement(depXml, 'groupId');\n const artifactId = extractXmlElement(depXml, 'artifactId');\n const version = extractXmlElement(depXml, 'version');\n const scope = extractXmlElement(depXml, 'scope');\n\n // Validate required fields\n if (!groupId || groupId.trim() === '') {\n logWarn(`[sec:maven] Missing groupId in dependency at ${relativeManifest} \u2014 skipping`);\n continue;\n }\n\n if (!artifactId || artifactId.trim() === '') {\n logWarn(`[sec:maven] Missing artifactId in dependency at ${relativeManifest} \u2014 skipping`);\n continue;\n }\n\n // Skip dependencies with unresolved Maven properties (e.g. ${project.version})\n if (groupId.includes('${') || artifactId.includes('${')) {\n logWarn(`[sec:maven] Unresolved property in dependency ${groupId}:${artifactId} at ${relativeManifest} \u2014 skipping`);\n continue;\n }\n\n // Build the dependency name as groupId:artifactId (Maven convention)\n const name = `${groupId}:${artifactId}`;\n\n // Version constraint \u2014 may be absent (managed by parent POM or BOM)\n let declaredConstraint: string;\n if (version && version.trim() !== '' && !version.includes('${')) {\n declaredConstraint = version.trim();\n } else {\n // No version or unresolved property \u2014 use empty string to indicate managed externally\n declaredConstraint = version && !version.includes('${') ? version.trim() : '';\n }\n\n const mappedScope = mapMavenScope(scope);\n\n dependencies.push({\n name,\n declaredConstraint,\n resolvedVersion: declaredConstraint || undefined,\n scope: mappedScope,\n ecosystem: 'maven',\n sourceManifest: relativeManifest,\n });\n }\n\n // Maven has no lock file, so a <dependency> with no explicit <version> (the\n // common case under a BOM parent like spring-boot-starter-parent) never gets\n // a resolvedVersion above, and packages pulled in only transitively (e.g.\n // tomcat-embed-core via spring-boot-starter-web) never appear in pom.xml at\n // all. If the project has a pre-generated `mvn dependency:tree` text file\n // (the closest Maven equivalent of a lock file), use it to fill in resolved\n // versions and capture transitive-only packages, mirroring how the npm\n // plugin layers package-lock.json on top of package.json.\n const manifestDir = path.dirname(manifestPath);\n const treeFile = findMavenDependencyTreeFile(manifestDir);\n\n if (treeFile) {\n const treeRelativePath = path.relative(projectRoot, treeFile.path).replace(/\\\\/g, '/');\n let treeContent: string;\n try {\n treeContent = fs.readFileSync(treeFile.path, 'utf8');\n } catch (err) {\n logWarn(`[sec:maven] Failed to read ${treeRelativePath}: ${err instanceof Error ? err.message : String(err)}`);\n applyLocalMavenLicenses(dependencies);\n return dependencies;\n }\n\n const treeEntries = parseMavenDependencyTree(treeContent);\n\n for (const dep of dependencies) {\n if (dep.resolvedVersion) continue;\n const treeEntry = treeEntries.get(dep.name);\n if (treeEntry) {\n dep.resolvedVersion = treeEntry.version;\n }\n }\n\n const directNames = new Set(dependencies.map(d => d.name));\n for (const [name, entry] of treeEntries) {\n if (directNames.has(name)) continue;\n dependencies.push({\n name,\n // No declared range exists at the project level for a transitive\n // package \u2014 the resolved version from the tree is the only constraint we have.\n declaredConstraint: entry.version,\n resolvedVersion: entry.version,\n scope: mapMavenScope(entry.scope),\n ecosystem: 'maven',\n sourceManifest: treeRelativePath,\n });\n }\n }\n\n applyLocalMavenLicenses(dependencies);\n return dependencies;\n}\n\n/**\n * Look for a pre-generated Maven dependency-tree text file next to pom.xml,\n * e.g. produced with:\n * mvn dependency:tree -DoutputFile=dependency-tree.txt\n * Checked locations, in order: `dependency-tree.txt` next to pom.xml, then\n * `target/dependency-tree.txt` (Maven's default build output directory).\n */\nfunction findMavenDependencyTreeFile(manifestDir: string): { path: string } | undefined {\n const candidates = ['dependency-tree.txt', path.join('target', 'dependency-tree.txt')];\n for (const candidate of candidates) {\n const candidatePath = path.join(manifestDir, candidate);\n if (fs.existsSync(candidatePath)) {\n return { path: candidatePath };\n }\n }\n return undefined;\n}\n\n/**\n * Parse `mvn dependency:tree` text output into a map of `groupId:artifactId`\n * to its resolved version and scope.\n *\n * Handles both:\n * groupId:artifactId:type:version:scope\n * groupId:artifactId:type:classifier:version:scope\n *\n * Skips the root project line (no scope segment) and parenthesized entries\n * like `(commons-logging:commons-logging:jar:1.1.1:compile - omitted for conflict with 1.2)`\n * \u2014 Maven's conflict resolution means only the winning version ends up on the\n * classpath, so omitted entries aren't actually present in the build.\n */\nexport function parseMavenDependencyTree(content: string): Map<string, { version: string; scope: string }> {\n const result = new Map<string, { version: string; scope: string }>();\n\n for (const rawLine of content.split(/\\r?\\n/)) {\n if (!rawLine.trim()) continue;\n\n // Strip Maven's ASCII tree-drawing prefix (e.g. \"| +- \", \" \\- \")\n const stripped = rawLine.replace(/^[\\s|+\\\\-]+/, '').trim();\n if (!stripped || stripped.startsWith('(')) continue;\n\n const parts = stripped.split(':');\n if (parts.length < 5) continue; // root project line (\"groupId:artifactId:version\") or malformed\n\n const groupId = parts[0];\n const artifactId = parts[1];\n const version = parts[parts.length - 2];\n const scope = parts[parts.length - 1];\n if (!groupId || !artifactId || !version) continue;\n\n const name = `${groupId}:${artifactId}`;\n if (!result.has(name)) {\n result.set(name, { version, scope });\n }\n }\n\n return result;\n}\n\n/**\n * Extract every license name from a pom.xml `<licenses>` block, in document\n * order. Looks for: <licenses><license><name>...</name></license>...</licenses>\n * Works on any pom.xml content \u2014 the project's own, or a dependency's own\n * POM read from the local Maven repository.\n */\nfunction extractMavenLicenseNames(content: string): string[] {\n const licensesMatch = content.match(/<licenses\\b[^>]*>([\\s\\S]*?)<\\/licenses>/i);\n if (!licensesMatch) return [];\n const licenseBlock = licensesMatch[1];\n const names: string[] = [];\n const licenseEntryRegex = /<license\\b[^>]*>([\\s\\S]*?)<\\/license>/gi;\n let entryMatch: RegExpExecArray | null;\n while ((entryMatch = licenseEntryRegex.exec(licenseBlock)) !== null) {\n const nameMatch = entryMatch[1].match(/<name>([^<]+)<\\/name>/i);\n if (nameMatch && nameMatch[1].trim() !== '') {\n names.push(nameMatch[1].trim());\n }\n }\n return names;\n}\n\n/**\n * Extract a pom.xml's license(s) as a single string. Multiple `<license>`\n * entries (dual/multi-licensed packages) are joined with \" OR \", matching\n * the SPDX-expression style already used for npm/Cargo license strings.\n */\nfunction extractMavenLicense(content: string): string | undefined {\n const names = extractMavenLicenseNames(content);\n return names.length > 0 ? names.join(' OR ') : undefined;\n}\n\n/**\n * Extract a pom.xml's `<parent>` coordinates, if present.\n * Looks for: <parent><groupId>...</groupId><artifactId>...</artifactId><version>...</version></parent>\n */\nfunction extractMavenParentCoords(content: string): { groupId: string; artifactId: string; version: string } | undefined {\n const parentMatch = content.match(/<parent\\b[^>]*>([\\s\\S]*?)<\\/parent>/i);\n if (!parentMatch) return undefined;\n const block = parentMatch[1];\n const groupId = extractXmlElement(block, 'groupId');\n const artifactId = extractXmlElement(block, 'artifactId');\n const version = extractXmlElement(block, 'version');\n if (!groupId || !artifactId || !version) return undefined;\n return { groupId, artifactId, version };\n}\n\n/**\n * Resolve the local Maven repository root: `~/.m2/settings.xml`'s\n * `<localRepository>` override if set, else the conventional `~/.m2/repository`.\n */\nfunction resolveMavenLocalRepoRoot(): string {\n const settingsPath = path.join(os.homedir(), '.m2', 'settings.xml');\n try {\n const settings = fs.readFileSync(settingsPath, 'utf8');\n const match = settings.match(/<localRepository>([^<]+)<\\/localRepository>/i);\n if (match && match[1].trim() !== '') return match[1].trim();\n } catch {\n // No settings.xml, or unreadable \u2014 fall through to the default.\n }\n return path.join(os.homedir(), '.m2', 'repository');\n}\n\n/**\n * Maven POMs commonly omit `<licenses>` and inherit it from a `<parent>` POM\n * instead \u2014 often several levels up (e.g. commons-codec -> commons-parent ->\n * the ASF parent). This caps how far up that chain is followed, both to\n * bound the number of file reads and to guard against a malformed/cyclic\n * parent reference.\n */\nconst MAX_MAVEN_PARENT_DEPTH = 10;\n\n/**\n * Each dependency's own license lives in its own POM, not the consuming\n * project's \u2014 Maven has no lock file to carry that data, but a dependency\n * that has ever been built or downloaded locally has its POM cached at the\n * standard local-repository layout:\n * <repoRoot>/<groupId with . -> />/<artifactId>/<version>/<artifactId>-<version>.pom\n * When that POM has no `<licenses>` of its own, its `<parent>` POM is tried\n * next (also read from the local repository), and so on up the chain \u2014 this\n * is exactly how Maven itself resolves inherited license metadata.\n * Local files only, no network calls. Returns undefined as soon as a POM in\n * the chain isn't cached locally (e.g. CI running from a clean cache) or no\n * POM in the chain declares a license \u2014 same as before this fix, this fills\n * in real data on top of an \"unknown\" default, it never invents one.\n */\nfunction findLocalMavenPomLicense(repoRoot: string, groupId: string, artifactId: string, version: string): string | undefined {\n let coords: { groupId: string; artifactId: string; version: string } | undefined = { groupId, artifactId, version };\n\n for (let depth = 0; coords && depth < MAX_MAVEN_PARENT_DEPTH; depth++) {\n const pomPath = path.join(repoRoot, ...coords.groupId.split('.'), coords.artifactId, coords.version, `${coords.artifactId}-${coords.version}.pom`);\n let content: string;\n try {\n content = fs.readFileSync(pomPath, 'utf8');\n } catch {\n return undefined;\n }\n\n const license = extractMavenLicense(content);\n if (license !== undefined) return license;\n\n coords = extractMavenParentCoords(content);\n }\n\n return undefined;\n}\n\n/**\n * Fill in `license` for every dependency that has a resolved version, by\n * reading that exact groupId:artifactId:version's own POM from the local\n * Maven repository. Mutates `dependencies` in place.\n */\nfunction applyLocalMavenLicenses(dependencies: ParsedDependency[]): void {\n const repoRoot = resolveMavenLocalRepoRoot();\n for (const dep of dependencies) {\n if (!dep.resolvedVersion) continue;\n const [groupId, artifactId] = dep.name.split(':');\n if (!groupId || !artifactId) continue;\n const license = findLocalMavenPomLicense(repoRoot, groupId, artifactId, dep.resolvedVersion);\n if (license !== undefined) dep.license = license;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED