kirograph 0.17.0 → 0.19.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.
- package/LICENSE +1 -1
- package/README.md +103 -1822
- package/dist/architecture/layers/dart.js +112 -0
- package/dist/architecture/layers/dart.js.map +7 -0
- package/dist/architecture/layers/index.js +3 -1
- package/dist/architecture/layers/index.js.map +2 -2
- package/dist/bin/banner.js +74 -6
- package/dist/bin/banner.js.map +2 -2
- package/dist/bin/commands/attack-surface.js +157 -0
- package/dist/bin/commands/attack-surface.js.map +7 -0
- package/dist/bin/commands/benchmark.js +206 -0
- package/dist/bin/commands/benchmark.js.map +7 -0
- package/dist/bin/commands/budget.js +70 -0
- package/dist/bin/commands/budget.js.map +7 -0
- package/dist/bin/commands/communities.js +77 -0
- package/dist/bin/commands/communities.js.map +7 -0
- package/dist/bin/commands/dep-confusion.js +119 -0
- package/dist/bin/commands/dep-confusion.js.map +7 -0
- package/dist/bin/commands/export.js +304 -10
- package/dist/bin/commands/export.js.map +2 -2
- package/dist/bin/commands/flows.js +97 -0
- package/dist/bin/commands/flows.js.map +7 -0
- package/dist/bin/commands/help.js +382 -101
- package/dist/bin/commands/help.js.map +2 -2
- package/dist/bin/commands/install.js +90 -8
- package/dist/bin/commands/install.js.map +2 -2
- package/dist/bin/commands/licenses.js +201 -0
- package/dist/bin/commands/licenses.js.map +7 -0
- package/dist/bin/commands/reachability.js +160 -0
- package/dist/bin/commands/reachability.js.map +7 -0
- package/dist/bin/commands/read.js +100 -0
- package/dist/bin/commands/read.js.map +7 -0
- package/dist/bin/commands/refactor.js +116 -0
- package/dist/bin/commands/refactor.js.map +7 -0
- package/dist/bin/commands/remediation.js +133 -0
- package/dist/bin/commands/remediation.js.map +7 -0
- package/dist/bin/commands/sbom.js +76 -0
- package/dist/bin/commands/sbom.js.map +7 -0
- package/dist/bin/commands/security-ci-report.js +267 -0
- package/dist/bin/commands/security-ci-report.js.map +7 -0
- package/dist/bin/commands/security-export.js +1349 -0
- package/dist/bin/commands/security-export.js.map +7 -0
- package/dist/bin/commands/security-flows.js +126 -0
- package/dist/bin/commands/security-flows.js.map +7 -0
- package/dist/bin/commands/security-secrets.js +170 -0
- package/dist/bin/commands/security-secrets.js.map +7 -0
- package/dist/bin/commands/security.js +193 -0
- package/dist/bin/commands/security.js.map +7 -0
- package/dist/bin/commands/staleness.js +144 -0
- package/dist/bin/commands/staleness.js.map +7 -0
- package/dist/bin/commands/status.js +102 -2
- package/dist/bin/commands/status.js.map +2 -2
- package/dist/bin/commands/supply-chain.js +138 -0
- package/dist/bin/commands/supply-chain.js.map +7 -0
- package/dist/bin/commands/uninit.js +109 -60
- package/dist/bin/commands/uninit.js.map +2 -2
- package/dist/bin/commands/vex.js +76 -0
- package/dist/bin/commands/vex.js.map +7 -0
- package/dist/bin/commands/vuln-suppress.js +95 -0
- package/dist/bin/commands/vuln-suppress.js.map +7 -0
- package/dist/bin/commands/vulns.js +382 -0
- package/dist/bin/commands/vulns.js.map +7 -0
- package/dist/bin/installer/auto-detect.js +125 -0
- package/dist/bin/installer/auto-detect.js.map +7 -0
- package/dist/bin/installer/cli-agent.js +28 -5
- package/dist/bin/installer/cli-agent.js.map +2 -2
- package/dist/bin/installer/common.js +47 -0
- package/dist/bin/installer/common.js.map +2 -2
- package/dist/bin/installer/config-prompt.js +12 -1
- package/dist/bin/installer/config-prompt.js.map +2 -2
- package/dist/bin/installer/detect.js +309 -0
- package/dist/bin/installer/detect.js.map +7 -0
- package/dist/bin/installer/index.js +9 -1
- package/dist/bin/installer/index.js.map +2 -2
- package/dist/bin/installer/instructions.js +195 -3
- package/dist/bin/installer/instructions.js.map +2 -2
- package/dist/bin/installer/steering.js +407 -0
- package/dist/bin/installer/steering.js.map +2 -2
- package/dist/bin/installer/targets/aider.js +3 -3
- package/dist/bin/installer/targets/aider.js.map +2 -2
- package/dist/bin/installer/targets/amp.js +3 -3
- package/dist/bin/installer/targets/amp.js.map +2 -2
- package/dist/bin/installer/targets/antigravity.js +35 -6
- package/dist/bin/installer/targets/antigravity.js.map +2 -2
- package/dist/bin/installer/targets/augment.js +3 -3
- package/dist/bin/installer/targets/augment.js.map +2 -2
- package/dist/bin/installer/targets/claude.js +49 -5
- package/dist/bin/installer/targets/claude.js.map +2 -2
- package/dist/bin/installer/targets/cline.js +32 -6
- package/dist/bin/installer/targets/cline.js.map +2 -2
- package/dist/bin/installer/targets/codex.js +64 -12
- package/dist/bin/installer/targets/codex.js.map +2 -2
- package/dist/bin/installer/targets/continue.js +2 -2
- package/dist/bin/installer/targets/continue.js.map +2 -2
- package/dist/bin/installer/targets/copilot-cli.js +101 -0
- package/dist/bin/installer/targets/copilot-cli.js.map +7 -0
- package/dist/bin/installer/targets/copilot.js +31 -5
- package/dist/bin/installer/targets/copilot.js.map +2 -2
- package/dist/bin/installer/targets/cursor.js +4 -4
- package/dist/bin/installer/targets/cursor.js.map +2 -2
- package/dist/bin/installer/targets/devin.js +2 -2
- package/dist/bin/installer/targets/devin.js.map +2 -2
- package/dist/bin/installer/targets/gemini-cli.js +2 -2
- package/dist/bin/installer/targets/gemini-cli.js.map +2 -2
- package/dist/bin/installer/targets/generic.js +2 -14
- package/dist/bin/installer/targets/generic.js.map +2 -2
- package/dist/bin/installer/targets/goose.js +3 -3
- package/dist/bin/installer/targets/goose.js.map +2 -2
- package/dist/bin/installer/targets/index.js +250 -0
- package/dist/bin/installer/targets/index.js.map +2 -2
- package/dist/bin/installer/targets/junie.js +2 -2
- package/dist/bin/installer/targets/junie.js.map +2 -2
- package/dist/bin/installer/targets/kilo.js +2 -2
- package/dist/bin/installer/targets/kilo.js.map +2 -2
- package/dist/bin/installer/targets/kiro.js +3 -3
- package/dist/bin/installer/targets/kiro.js.map +2 -2
- package/dist/bin/installer/targets/opencode.js +2 -2
- package/dist/bin/installer/targets/opencode.js.map +2 -2
- package/dist/bin/installer/targets/openhands.js +3 -3
- package/dist/bin/installer/targets/openhands.js.map +2 -2
- package/dist/bin/installer/targets/qoder.js +91 -0
- package/dist/bin/installer/targets/qoder.js.map +7 -0
- package/dist/bin/installer/targets/qwen.js +96 -0
- package/dist/bin/installer/targets/qwen.js.map +7 -0
- package/dist/bin/installer/targets/replit.js +3 -3
- package/dist/bin/installer/targets/replit.js.map +2 -2
- package/dist/bin/installer/targets/roo.js +2 -2
- package/dist/bin/installer/targets/roo.js.map +2 -2
- package/dist/bin/installer/targets/tabnine.js +3 -3
- package/dist/bin/installer/targets/tabnine.js.map +2 -2
- package/dist/bin/installer/targets/trae.js +5 -5
- package/dist/bin/installer/targets/trae.js.map +2 -2
- package/dist/bin/installer/targets/warp.js +2 -2
- package/dist/bin/installer/targets/warp.js.map +2 -2
- package/dist/bin/installer/targets/windsurf.js +35 -6
- package/dist/bin/installer/targets/windsurf.js.map +2 -2
- package/dist/bin/kirograph.js +72 -6
- package/dist/bin/kirograph.js.map +3 -3
- package/dist/compression/tracker.js +80 -0
- package/dist/compression/tracker.js.map +2 -2
- package/dist/config.js +90 -3
- package/dist/config.js.map +2 -2
- package/dist/core/pipeline.js +36 -2
- package/dist/core/pipeline.js.map +2 -2
- package/dist/db/database.js +56 -5
- package/dist/db/database.js.map +2 -2
- package/dist/db/memory-schema.sql +5 -1
- package/dist/db/schema.sql +3 -1
- package/dist/db/security-schema.sql +72 -0
- package/dist/extraction/extractor.js +81 -0
- package/dist/extraction/extractor.js.map +2 -2
- package/dist/extraction/grammars.js +32 -8
- package/dist/extraction/grammars.js.map +2 -2
- package/dist/extraction/languages.js +43 -1
- package/dist/extraction/languages.js.map +2 -2
- package/dist/extraction/notebook.js +300 -0
- package/dist/extraction/notebook.js.map +7 -0
- package/dist/extraction/wasm/tree-sitter-astro.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-gdscript.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-julia.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-perl.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-powershell.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-r.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-sql.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-verilog.wasm +0 -0
- package/dist/frameworks/flutter.js +130 -0
- package/dist/frameworks/flutter.js.map +7 -0
- package/dist/frameworks/index.js +7 -1
- package/dist/frameworks/index.js.map +3 -3
- package/dist/graph/communities.js +317 -0
- package/dist/graph/communities.js.map +7 -0
- package/dist/graph/flows.js +138 -0
- package/dist/graph/flows.js.map +7 -0
- package/dist/graph/refactor.js +155 -0
- package/dist/graph/refactor.js.map +7 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +2 -2
- package/dist/mcp/cache.js +172 -0
- package/dist/mcp/cache.js.map +7 -0
- package/dist/mcp/read-modes.js +295 -0
- package/dist/mcp/read-modes.js.map +7 -0
- package/dist/mcp/server.js +2 -1
- package/dist/mcp/server.js.map +2 -2
- package/dist/mcp/tool-names.js +21 -1
- package/dist/mcp/tool-names.js.map +2 -2
- package/dist/mcp/tools.js +1160 -1
- package/dist/mcp/tools.js.map +3 -3
- package/dist/memory/database.js +32 -2
- package/dist/memory/database.js.map +2 -2
- package/dist/memory/types.js.map +1 -1
- package/dist/resolution/bridges/android-rn.js +298 -0
- package/dist/resolution/bridges/android-rn.js.map +7 -0
- package/dist/resolution/bridges/expo-modules.js +155 -0
- package/dist/resolution/bridges/expo-modules.js.map +7 -0
- package/dist/resolution/bridges/flutter-channel.js +385 -0
- package/dist/resolution/bridges/flutter-channel.js.map +7 -0
- package/dist/resolution/bridges/index.js +80 -0
- package/dist/resolution/bridges/index.js.map +7 -0
- package/dist/resolution/bridges/native-events.js +188 -0
- package/dist/resolution/bridges/native-events.js.map +7 -0
- package/dist/resolution/bridges/native-views.js +244 -0
- package/dist/resolution/bridges/native-views.js.map +7 -0
- package/dist/resolution/bridges/react-native.js +161 -0
- package/dist/resolution/bridges/react-native.js.map +7 -0
- package/dist/resolution/bridges/swift-objc.js +227 -0
- package/dist/resolution/bridges/swift-objc.js.map +7 -0
- package/dist/resolution/bridges/turbomodules.js +216 -0
- package/dist/resolution/bridges/turbomodules.js.map +7 -0
- package/dist/resolution/index.js +61 -2
- package/dist/resolution/index.js.map +2 -2
- package/dist/security/attack-surface.js +164 -0
- package/dist/security/attack-surface.js.map +7 -0
- package/dist/security/context-warnings.js +123 -0
- package/dist/security/context-warnings.js.map +7 -0
- package/dist/security/context-warnings.test.js +300 -0
- package/dist/security/context-warnings.test.js.map +7 -0
- package/dist/security/data-flows.js +228 -0
- package/dist/security/data-flows.js.map +7 -0
- package/dist/security/dep-confusion.js +255 -0
- package/dist/security/dep-confusion.js.map +7 -0
- package/dist/security/errors.js +51 -0
- package/dist/security/errors.js.map +7 -0
- package/dist/security/export/fix-suggestions.js +58 -0
- package/dist/security/export/fix-suggestions.js.map +7 -0
- package/dist/security/export/fix-suggestions.test.js +74 -0
- package/dist/security/export/fix-suggestions.test.js.map +7 -0
- package/dist/security/export/sbom.js +230 -0
- package/dist/security/export/sbom.js.map +7 -0
- package/dist/security/export/sbom.test.js +288 -0
- package/dist/security/export/sbom.test.js.map +7 -0
- package/dist/security/export/serialization.js +142 -0
- package/dist/security/export/serialization.js.map +7 -0
- package/dist/security/export/serialization.test.js +310 -0
- package/dist/security/export/serialization.test.js.map +7 -0
- package/dist/security/export/vex.js +220 -0
- package/dist/security/export/vex.js.map +7 -0
- package/dist/security/export/vex.test.js +278 -0
- package/dist/security/export/vex.test.js.map +7 -0
- package/dist/security/index.js +67 -0
- package/dist/security/index.js.map +7 -0
- package/dist/security/integrator-transitives.test.js +359 -0
- package/dist/security/integrator-transitives.test.js.map +7 -0
- package/dist/security/integrator.js +491 -0
- package/dist/security/integrator.js.map +7 -0
- package/dist/security/integrator.test.js +237 -0
- package/dist/security/integrator.test.js.map +7 -0
- package/dist/security/license.js +70 -0
- package/dist/security/license.js.map +7 -0
- package/dist/security/manifest/adapter.js +243 -0
- package/dist/security/manifest/adapter.js.map +7 -0
- package/dist/security/manifest/adapter.test.js +272 -0
- package/dist/security/manifest/adapter.test.js.map +7 -0
- package/dist/security/manifest/parser.js +376 -0
- package/dist/security/manifest/parser.js.map +7 -0
- package/dist/security/manifest/parser.test.js +110 -0
- package/dist/security/manifest/parser.test.js.map +7 -0
- package/dist/security/manifest/plugins/cargo.js +233 -0
- package/dist/security/manifest/plugins/cargo.js.map +7 -0
- package/dist/security/manifest/plugins/cargo.test.js +304 -0
- package/dist/security/manifest/plugins/cargo.test.js.map +7 -0
- package/dist/security/manifest/plugins/composer.js +152 -0
- package/dist/security/manifest/plugins/composer.js.map +7 -0
- package/dist/security/manifest/plugins/go.js +146 -0
- package/dist/security/manifest/plugins/go.js.map +7 -0
- package/dist/security/manifest/plugins/go.test.js +341 -0
- package/dist/security/manifest/plugins/go.test.js.map +7 -0
- package/dist/security/manifest/plugins/gradle.js +159 -0
- package/dist/security/manifest/plugins/gradle.js.map +7 -0
- package/dist/security/manifest/plugins/hex.js +159 -0
- package/dist/security/manifest/plugins/hex.js.map +7 -0
- package/dist/security/manifest/plugins/maven.js +128 -0
- package/dist/security/manifest/plugins/maven.js.map +7 -0
- package/dist/security/manifest/plugins/maven.test.js +389 -0
- package/dist/security/manifest/plugins/maven.test.js.map +7 -0
- package/dist/security/manifest/plugins/npm.js +284 -0
- package/dist/security/manifest/plugins/npm.js.map +7 -0
- package/dist/security/manifest/plugins/npm.test.js +298 -0
- package/dist/security/manifest/plugins/npm.test.js.map +7 -0
- package/dist/security/manifest/plugins/nuget.js +186 -0
- package/dist/security/manifest/plugins/nuget.js.map +7 -0
- package/dist/security/manifest/plugins/pip.js +123 -0
- package/dist/security/manifest/plugins/pip.js.map +7 -0
- package/dist/security/manifest/plugins/pip.test.js +208 -0
- package/dist/security/manifest/plugins/pip.test.js.map +7 -0
- package/dist/security/manifest/plugins/pubspec.js +212 -0
- package/dist/security/manifest/plugins/pubspec.js.map +7 -0
- package/dist/security/manifest/plugins/pyproject.js +261 -0
- package/dist/security/manifest/plugins/pyproject.js.map +7 -0
- package/dist/security/manifest/plugins/rubygems.js +185 -0
- package/dist/security/manifest/plugins/rubygems.js.map +7 -0
- package/dist/security/manifest/plugins/swift.js +200 -0
- package/dist/security/manifest/plugins/swift.js.map +7 -0
- package/dist/security/owasp.js +104 -0
- package/dist/security/owasp.js.map +7 -0
- package/dist/security/pipeline.js +125 -0
- package/dist/security/pipeline.js.map +7 -0
- package/dist/security/reachability.js +276 -0
- package/dist/security/reachability.js.map +7 -0
- package/dist/security/reachability.test.js +394 -0
- package/dist/security/reachability.test.js.map +7 -0
- package/dist/security/remediation.js +126 -0
- package/dist/security/remediation.js.map +7 -0
- package/dist/security/secrets.js +176 -0
- package/dist/security/secrets.js.map +7 -0
- package/dist/security/staleness.js +231 -0
- package/dist/security/staleness.js.map +7 -0
- package/dist/security/supply-chain.js +301 -0
- package/dist/security/supply-chain.js.map +7 -0
- package/dist/security/suppressions.js +106 -0
- package/dist/security/suppressions.js.map +7 -0
- package/dist/security/types.js +17 -0
- package/dist/security/types.js.map +7 -0
- package/dist/security/vuln/client.js +355 -0
- package/dist/security/vuln/client.js.map +7 -0
- package/dist/security/vuln/client.test.js +288 -0
- package/dist/security/vuln/client.test.js.map +7 -0
- package/dist/security/vuln/epss-client.js +95 -0
- package/dist/security/vuln/epss-client.js.map +7 -0
- package/dist/security/vuln/index.js +29 -0
- package/dist/security/vuln/index.js.map +7 -0
- package/dist/security/vuln/osv-adapter.js +321 -0
- package/dist/security/vuln/osv-adapter.js.map +7 -0
- package/dist/security/vuln/osv-adapter.test.js +391 -0
- package/dist/security/vuln/osv-adapter.test.js.map +7 -0
- package/dist/security/vuln/types.js +17 -0
- package/dist/security/vuln/types.js.map +7 -0
- package/dist/types.js.map +2 -2
- package/package.json +2 -1
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var parser_exports = {};
|
|
20
|
+
__export(parser_exports, {
|
|
21
|
+
ManifestParser: () => ManifestParser,
|
|
22
|
+
compareVersions: () => compareVersions,
|
|
23
|
+
deduplicateDependencies: () => deduplicateDependencies
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(parser_exports);
|
|
26
|
+
var import_adapter = require("./adapter");
|
|
27
|
+
var import_npm = require("./plugins/npm");
|
|
28
|
+
var import_maven = require("./plugins/maven");
|
|
29
|
+
var import_go = require("./plugins/go");
|
|
30
|
+
var import_pip = require("./plugins/pip");
|
|
31
|
+
var import_cargo = require("./plugins/cargo");
|
|
32
|
+
var import_nuget = require("./plugins/nuget");
|
|
33
|
+
var import_gradle = require("./plugins/gradle");
|
|
34
|
+
var import_rubygems = require("./plugins/rubygems");
|
|
35
|
+
var import_composer = require("./plugins/composer");
|
|
36
|
+
var import_swift = require("./plugins/swift");
|
|
37
|
+
var import_pubspec = require("./plugins/pubspec");
|
|
38
|
+
var import_hex = require("./plugins/hex");
|
|
39
|
+
var import_pyproject = require("./plugins/pyproject");
|
|
40
|
+
var import_errors = require("../../errors");
|
|
41
|
+
function createNpmPlugin() {
|
|
42
|
+
return {
|
|
43
|
+
ecosystem: "npm",
|
|
44
|
+
manifestFiles: ["package.json"],
|
|
45
|
+
canExtract(manifestPath) {
|
|
46
|
+
return manifestPath.endsWith("package.json");
|
|
47
|
+
},
|
|
48
|
+
extract: import_npm.parseNpmManifest
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function createMavenPlugin() {
|
|
52
|
+
return {
|
|
53
|
+
ecosystem: "maven",
|
|
54
|
+
manifestFiles: ["pom.xml"],
|
|
55
|
+
canExtract(manifestPath) {
|
|
56
|
+
return manifestPath.endsWith("pom.xml");
|
|
57
|
+
},
|
|
58
|
+
extract: import_maven.parseMavenManifest
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function createGoPlugin() {
|
|
62
|
+
return {
|
|
63
|
+
ecosystem: "go",
|
|
64
|
+
manifestFiles: ["go.mod"],
|
|
65
|
+
canExtract(manifestPath) {
|
|
66
|
+
return manifestPath.endsWith("go.mod");
|
|
67
|
+
},
|
|
68
|
+
extract: import_go.parseGoManifest
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function createPipPlugin() {
|
|
72
|
+
return {
|
|
73
|
+
ecosystem: "python",
|
|
74
|
+
manifestFiles: ["requirements.txt"],
|
|
75
|
+
canExtract(manifestPath) {
|
|
76
|
+
return manifestPath.endsWith("requirements.txt");
|
|
77
|
+
},
|
|
78
|
+
extract: import_pip.parsePipManifest
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function createCargoPlugin() {
|
|
82
|
+
return {
|
|
83
|
+
ecosystem: "cargo",
|
|
84
|
+
manifestFiles: ["Cargo.toml"],
|
|
85
|
+
canExtract(manifestPath) {
|
|
86
|
+
return manifestPath.endsWith("Cargo.toml");
|
|
87
|
+
},
|
|
88
|
+
extract: import_cargo.parseCargoManifest
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function createNugetPlugin() {
|
|
92
|
+
return {
|
|
93
|
+
ecosystem: "csproj",
|
|
94
|
+
manifestFiles: [".csproj"],
|
|
95
|
+
canExtract(manifestPath) {
|
|
96
|
+
return manifestPath.endsWith(".csproj");
|
|
97
|
+
},
|
|
98
|
+
extract: import_nuget.parseNugetManifest
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function createGradlePlugin() {
|
|
102
|
+
return {
|
|
103
|
+
ecosystem: "gradle",
|
|
104
|
+
manifestFiles: ["build.gradle", "build.gradle.kts"],
|
|
105
|
+
canExtract(manifestPath) {
|
|
106
|
+
const base = manifestPath.split("/").pop() ?? "";
|
|
107
|
+
return base === "build.gradle" || base === "build.gradle.kts";
|
|
108
|
+
},
|
|
109
|
+
extract: import_gradle.parseGradleManifest
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function createPyprojectPlugin() {
|
|
113
|
+
return {
|
|
114
|
+
ecosystem: "pyproject",
|
|
115
|
+
manifestFiles: ["pyproject.toml"],
|
|
116
|
+
canExtract(manifestPath) {
|
|
117
|
+
return manifestPath.endsWith("pyproject.toml");
|
|
118
|
+
},
|
|
119
|
+
extract: import_pyproject.parsePyprojectManifest
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function createRubygemsPlugin() {
|
|
123
|
+
return {
|
|
124
|
+
ecosystem: "rubygems",
|
|
125
|
+
manifestFiles: ["Gemfile"],
|
|
126
|
+
canExtract(manifestPath) {
|
|
127
|
+
return manifestPath.endsWith("/Gemfile") || manifestPath === "Gemfile";
|
|
128
|
+
},
|
|
129
|
+
extract: import_rubygems.parseRubygemsManifest
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function createComposerPlugin() {
|
|
133
|
+
return {
|
|
134
|
+
ecosystem: "composer",
|
|
135
|
+
manifestFiles: ["composer.json"],
|
|
136
|
+
canExtract(manifestPath) {
|
|
137
|
+
return manifestPath.endsWith("composer.json");
|
|
138
|
+
},
|
|
139
|
+
extract: import_composer.parseComposerManifest
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function createSwiftPlugin() {
|
|
143
|
+
return {
|
|
144
|
+
ecosystem: "swift",
|
|
145
|
+
manifestFiles: ["Package.swift"],
|
|
146
|
+
canExtract(manifestPath) {
|
|
147
|
+
return manifestPath.endsWith("Package.swift");
|
|
148
|
+
},
|
|
149
|
+
extract: import_swift.parseSwiftManifest
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function createPubspecPlugin() {
|
|
153
|
+
return {
|
|
154
|
+
ecosystem: "pub",
|
|
155
|
+
manifestFiles: ["pubspec.yaml"],
|
|
156
|
+
canExtract(manifestPath) {
|
|
157
|
+
return manifestPath.endsWith("pubspec.yaml");
|
|
158
|
+
},
|
|
159
|
+
extract: import_pubspec.parsePubspecManifest
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function createHexPlugin() {
|
|
163
|
+
return {
|
|
164
|
+
ecosystem: "hex",
|
|
165
|
+
manifestFiles: ["mix.exs"],
|
|
166
|
+
canExtract(manifestPath) {
|
|
167
|
+
return manifestPath.endsWith("mix.exs");
|
|
168
|
+
},
|
|
169
|
+
extract: import_hex.parseHexManifest
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function compareVersions(a, b) {
|
|
173
|
+
const cleanA = a.startsWith("v") ? a.slice(1) : a;
|
|
174
|
+
const cleanB = b.startsWith("v") ? b.slice(1) : b;
|
|
175
|
+
const numericA = cleanA.replace(/^[~^>=<]+/, "");
|
|
176
|
+
const numericB = cleanB.replace(/^[~^>=<]+/, "");
|
|
177
|
+
const partsA = numericA.split(".");
|
|
178
|
+
const partsB = numericB.split(".");
|
|
179
|
+
const maxLen = Math.max(partsA.length, partsB.length);
|
|
180
|
+
for (let i = 0; i < maxLen; i++) {
|
|
181
|
+
const segA = partsA[i] ?? "0";
|
|
182
|
+
const segB = partsB[i] ?? "0";
|
|
183
|
+
const numA = parseInt(segA, 10);
|
|
184
|
+
const numB = parseInt(segB, 10);
|
|
185
|
+
if (!isNaN(numA) && !isNaN(numB)) {
|
|
186
|
+
if (numA !== numB) return numA - numB;
|
|
187
|
+
const suffixA = segA.slice(String(numA).length);
|
|
188
|
+
const suffixB = segB.slice(String(numB).length);
|
|
189
|
+
if (suffixA !== suffixB) {
|
|
190
|
+
if (suffixA && !suffixB) return -1;
|
|
191
|
+
if (!suffixA && suffixB) return 1;
|
|
192
|
+
return suffixA.localeCompare(suffixB);
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
const cmp = segA.localeCompare(segB);
|
|
196
|
+
if (cmp !== 0) return cmp;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return 0;
|
|
200
|
+
}
|
|
201
|
+
function getEffectiveVersion(dep) {
|
|
202
|
+
return dep.resolvedVersion ?? dep.declaredConstraint;
|
|
203
|
+
}
|
|
204
|
+
function deduplicateDependencies(deps) {
|
|
205
|
+
const map = /* @__PURE__ */ new Map();
|
|
206
|
+
for (const dep of deps) {
|
|
207
|
+
const key = `${dep.ecosystem}:${dep.name}`;
|
|
208
|
+
const existing = map.get(key);
|
|
209
|
+
if (!existing) {
|
|
210
|
+
map.set(key, {
|
|
211
|
+
name: dep.name,
|
|
212
|
+
ecosystem: dep.ecosystem,
|
|
213
|
+
declaredConstraint: dep.declaredConstraint,
|
|
214
|
+
resolvedVersion: dep.resolvedVersion,
|
|
215
|
+
scope: dep.scope,
|
|
216
|
+
sourceManifests: [dep.sourceManifest],
|
|
217
|
+
license: dep.license
|
|
218
|
+
});
|
|
219
|
+
} else {
|
|
220
|
+
if (!existing.sourceManifests.includes(dep.sourceManifest)) {
|
|
221
|
+
existing.sourceManifests.push(dep.sourceManifest);
|
|
222
|
+
}
|
|
223
|
+
const existingVersion = existing.resolvedVersion ?? existing.declaredConstraint;
|
|
224
|
+
const newVersion = getEffectiveVersion(dep);
|
|
225
|
+
if (compareVersions(newVersion, existingVersion) > 0) {
|
|
226
|
+
existing.declaredConstraint = dep.declaredConstraint;
|
|
227
|
+
existing.resolvedVersion = dep.resolvedVersion;
|
|
228
|
+
existing.scope = dep.scope;
|
|
229
|
+
if (dep.license !== void 0) {
|
|
230
|
+
existing.license = dep.license;
|
|
231
|
+
}
|
|
232
|
+
} else if (existing.license === void 0 && dep.license !== void 0) {
|
|
233
|
+
existing.license = dep.license;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return [...map.values()];
|
|
238
|
+
}
|
|
239
|
+
class ManifestParser {
|
|
240
|
+
constructor(db, projectRoot) {
|
|
241
|
+
this.db = db;
|
|
242
|
+
this.projectRoot = projectRoot;
|
|
243
|
+
this.adapter = new import_adapter.SecurityManifestAdapter(projectRoot);
|
|
244
|
+
this.adapter.registerPlugin(createNpmPlugin());
|
|
245
|
+
this.adapter.registerPlugin(createMavenPlugin());
|
|
246
|
+
this.adapter.registerPlugin(createGoPlugin());
|
|
247
|
+
this.adapter.registerPlugin(createPipPlugin());
|
|
248
|
+
this.adapter.registerPlugin(createCargoPlugin());
|
|
249
|
+
this.adapter.registerPlugin(createNugetPlugin());
|
|
250
|
+
this.adapter.registerPlugin(createGradlePlugin());
|
|
251
|
+
this.adapter.registerStandalonePlugin(createPyprojectPlugin());
|
|
252
|
+
this.adapter.registerStandalonePlugin(createRubygemsPlugin());
|
|
253
|
+
this.adapter.registerStandalonePlugin(createComposerPlugin());
|
|
254
|
+
this.adapter.registerStandalonePlugin(createSwiftPlugin());
|
|
255
|
+
this.adapter.registerStandalonePlugin(createPubspecPlugin());
|
|
256
|
+
this.adapter.registerStandalonePlugin(createHexPlugin());
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Get the underlying adapter (useful for testing).
|
|
260
|
+
*/
|
|
261
|
+
getAdapter() {
|
|
262
|
+
return this.adapter;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Run full manifest discovery, parsing, deduplication, and database persistence.
|
|
266
|
+
*
|
|
267
|
+
* Steps:
|
|
268
|
+
* 1. Discover manifest files via the adapter (reuses architecture parsers)
|
|
269
|
+
* 2. Extract dependencies with version/scope data via registered plugins
|
|
270
|
+
* 3. Deduplicate: same (name, ecosystem) → single entry with highest version
|
|
271
|
+
* 4. Create Dependency_Nodes in the database (nodes + sec_dependencies tables)
|
|
272
|
+
* 5. Create `declared_in` edges linking dependencies to their source manifests
|
|
273
|
+
*/
|
|
274
|
+
async parseAll() {
|
|
275
|
+
const warnings = [];
|
|
276
|
+
const errors = [];
|
|
277
|
+
const allDeps = [];
|
|
278
|
+
const manifestPaths = this.adapter.discoverManifests();
|
|
279
|
+
let manifestsParsed = 0;
|
|
280
|
+
for (const manifestPath of manifestPaths) {
|
|
281
|
+
try {
|
|
282
|
+
const deps = await this.adapter.extractFromManifest(manifestPath);
|
|
283
|
+
if (deps.length > 0) {
|
|
284
|
+
allDeps.push(...deps);
|
|
285
|
+
manifestsParsed++;
|
|
286
|
+
} else {
|
|
287
|
+
manifestsParsed++;
|
|
288
|
+
}
|
|
289
|
+
} catch (err) {
|
|
290
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
291
|
+
const relPath = manifestPath.replace(this.projectRoot + "/", "").replace(/\\/g, "/");
|
|
292
|
+
errors.push({ file: relPath, message });
|
|
293
|
+
(0, import_errors.logError)(`[sec:parser] Failed to parse manifest ${relPath}: ${message}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (allDeps.length === 0) {
|
|
297
|
+
return {
|
|
298
|
+
dependenciesCreated: 0,
|
|
299
|
+
manifestsParsed,
|
|
300
|
+
warnings,
|
|
301
|
+
errors
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
const deduplicated = deduplicateDependencies(allDeps);
|
|
305
|
+
let dependenciesCreated = 0;
|
|
306
|
+
const rawDb = this.db.getRawDb();
|
|
307
|
+
for (const dep of deduplicated) {
|
|
308
|
+
try {
|
|
309
|
+
const nodeId = `dep:${dep.ecosystem}:${dep.name}`;
|
|
310
|
+
const node = {
|
|
311
|
+
id: nodeId,
|
|
312
|
+
kind: "dependency",
|
|
313
|
+
name: dep.name,
|
|
314
|
+
qualifiedName: `${dep.ecosystem}/${dep.name}`,
|
|
315
|
+
filePath: dep.sourceManifests[0] ?? "",
|
|
316
|
+
language: "unknown",
|
|
317
|
+
startLine: 0,
|
|
318
|
+
endLine: 0,
|
|
319
|
+
startColumn: 0,
|
|
320
|
+
endColumn: 0,
|
|
321
|
+
signature: dep.resolvedVersion ?? dep.declaredConstraint,
|
|
322
|
+
isExported: false,
|
|
323
|
+
isAsync: false,
|
|
324
|
+
isStatic: false,
|
|
325
|
+
isAbstract: false,
|
|
326
|
+
updatedAt: Date.now()
|
|
327
|
+
};
|
|
328
|
+
this.db.upsertNode(node);
|
|
329
|
+
rawDb.run(
|
|
330
|
+
`INSERT OR REPLACE INTO sec_dependencies
|
|
331
|
+
(node_id, ecosystem, package_name, declared_constraint, resolved_version, scope, source_manifests, license)
|
|
332
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
333
|
+
[
|
|
334
|
+
nodeId,
|
|
335
|
+
dep.ecosystem,
|
|
336
|
+
dep.name,
|
|
337
|
+
dep.declaredConstraint,
|
|
338
|
+
dep.resolvedVersion ?? null,
|
|
339
|
+
dep.scope,
|
|
340
|
+
JSON.stringify(dep.sourceManifests),
|
|
341
|
+
dep.license ?? null
|
|
342
|
+
]
|
|
343
|
+
);
|
|
344
|
+
for (const manifest of dep.sourceManifests) {
|
|
345
|
+
const edge = {
|
|
346
|
+
source: nodeId,
|
|
347
|
+
target: manifest,
|
|
348
|
+
kind: "declared_in"
|
|
349
|
+
};
|
|
350
|
+
this.db.insertEdge(edge);
|
|
351
|
+
}
|
|
352
|
+
dependenciesCreated++;
|
|
353
|
+
} catch (err) {
|
|
354
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
355
|
+
warnings.push({
|
|
356
|
+
file: dep.sourceManifests[0] ?? "unknown",
|
|
357
|
+
message: `Failed to persist dependency ${dep.ecosystem}/${dep.name}: ${message}`
|
|
358
|
+
});
|
|
359
|
+
(0, import_errors.logWarn)(`[sec:parser] Failed to persist dependency ${dep.ecosystem}/${dep.name}: ${message}`);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
dependenciesCreated,
|
|
364
|
+
manifestsParsed,
|
|
365
|
+
warnings,
|
|
366
|
+
errors
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
371
|
+
0 && (module.exports = {
|
|
372
|
+
ManifestParser,
|
|
373
|
+
compareVersions,
|
|
374
|
+
deduplicateDependencies
|
|
375
|
+
});
|
|
376
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/security/manifest/parser.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * ManifestParser Orchestrator\n *\n * Orchestrates manifest discovery, version extraction, deduplication, and\n * database persistence. Uses the SecurityManifestAdapter for discovery and\n * extraction, registers all 12 version extraction plugins:\n * Wrapped (arch parser exists): npm, maven, go, pip, cargo, nuget, gradle\n * Standalone (no arch parser): rubygems, composer, swift, pubspec, hex\n *\n * Node ID format: `dep:<ecosystem>:<name>` (e.g. `dep:npm:express`)\n */\nimport { SecurityManifestAdapter, type VersionExtractionPlugin } from './adapter';\nimport { parseNpmManifest } from './plugins/npm';\nimport { parseMavenManifest } from './plugins/maven';\nimport { parseGoManifest } from './plugins/go';\nimport { parsePipManifest } from './plugins/pip';\nimport { parseCargoManifest } from './plugins/cargo';\nimport { parseNugetManifest } from './plugins/nuget';\nimport { parseGradleManifest } from './plugins/gradle';\nimport { parseRubygemsManifest } from './plugins/rubygems';\nimport { parseComposerManifest } from './plugins/composer';\nimport { parseSwiftManifest } from './plugins/swift';\nimport { parsePubspecManifest } from './plugins/pubspec';\nimport { parseHexManifest } from './plugins/hex';\nimport { parsePyprojectManifest } from './plugins/pyproject';\nimport type { GraphDatabase } from '../../db/database';\nimport type { ParsedDependency, ManifestParseResult } from '../types';\nimport type { Node, Edge } from '../../types';\nimport { logWarn, logError } from '../../errors';\n\n// \u2500\u2500 Plugin Definitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Create the npm version extraction plugin wrapping parseNpmManifest.\n */\nfunction createNpmPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'npm',\n manifestFiles: ['package.json'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('package.json');\n },\n extract: parseNpmManifest,\n };\n}\n\n/**\n * Create the Maven version extraction plugin wrapping parseMavenManifest.\n */\nfunction createMavenPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'maven',\n manifestFiles: ['pom.xml'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('pom.xml');\n },\n extract: parseMavenManifest,\n };\n}\n\n/**\n * Create the Go version extraction plugin wrapping parseGoManifest.\n */\nfunction createGoPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'go',\n manifestFiles: ['go.mod'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('go.mod');\n },\n extract: parseGoManifest,\n };\n}\n\n/**\n * Create the pip version extraction plugin wrapping parsePipManifest.\n */\nfunction createPipPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'python',\n manifestFiles: ['requirements.txt'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('requirements.txt');\n },\n extract: parsePipManifest,\n };\n}\n\n/**\n * Create the Cargo version extraction plugin wrapping parseCargoManifest.\n */\nfunction createCargoPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'cargo',\n manifestFiles: ['Cargo.toml'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('Cargo.toml');\n },\n extract: parseCargoManifest,\n };\n}\n\n/**\n * Create the NuGet version extraction plugin wrapping parseNugetManifest.\n * ecosystem = 'csproj' to match the architecture parser name for lookup;\n * ParsedDependency.ecosystem is set to 'nuget' inside the plugin function.\n */\nfunction createNugetPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'csproj',\n manifestFiles: ['.csproj'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('.csproj');\n },\n extract: parseNugetManifest,\n };\n}\n\n/**\n * Create the Gradle version extraction plugin wrapping parseGradleManifest.\n */\nfunction createGradlePlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'gradle',\n manifestFiles: ['build.gradle', 'build.gradle.kts'],\n canExtract(manifestPath: string): boolean {\n const base = manifestPath.split('/').pop() ?? '';\n return base === 'build.gradle' || base === 'build.gradle.kts';\n },\n extract: parseGradleManifest,\n };\n}\n\nfunction createPyprojectPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'pyproject',\n manifestFiles: ['pyproject.toml'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('pyproject.toml');\n },\n extract: parsePyprojectManifest,\n };\n}\n\n// \u2500\u2500 Standalone Plugin Factories \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction createRubygemsPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'rubygems',\n manifestFiles: ['Gemfile'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('/Gemfile') || manifestPath === 'Gemfile';\n },\n extract: parseRubygemsManifest,\n };\n}\n\nfunction createComposerPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'composer',\n manifestFiles: ['composer.json'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('composer.json');\n },\n extract: parseComposerManifest,\n };\n}\n\nfunction createSwiftPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'swift',\n manifestFiles: ['Package.swift'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('Package.swift');\n },\n extract: parseSwiftManifest,\n };\n}\n\nfunction createPubspecPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'pub',\n manifestFiles: ['pubspec.yaml'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('pubspec.yaml');\n },\n extract: parsePubspecManifest,\n };\n}\n\nfunction createHexPlugin(): VersionExtractionPlugin {\n return {\n ecosystem: 'hex',\n manifestFiles: ['mix.exs'],\n canExtract(manifestPath: string): boolean {\n return manifestPath.endsWith('mix.exs');\n },\n extract: parseHexManifest,\n };\n}\n\n// \u2500\u2500 Version Comparison \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Compare two version strings. Returns:\n * - positive if a > b\n * - negative if a < b\n * - 0 if equal\n *\n * Handles semver-like versions (1.2.3), Go pseudo-versions, and constraint\n * strings. Falls back to lexicographic comparison for non-numeric versions.\n */\nexport function compareVersions(a: string, b: string): number {\n // Strip leading 'v' (common in Go modules)\n const cleanA = a.startsWith('v') ? a.slice(1) : a;\n const cleanB = b.startsWith('v') ? b.slice(1) : b;\n\n // Strip common constraint prefixes (^, ~, >=, <=, =, >, <)\n const numericA = cleanA.replace(/^[~^>=<]+/, '');\n const numericB = cleanB.replace(/^[~^>=<]+/, '');\n\n const partsA = numericA.split('.');\n const partsB = numericB.split('.');\n\n const maxLen = Math.max(partsA.length, partsB.length);\n for (let i = 0; i < maxLen; i++) {\n const segA = partsA[i] ?? '0';\n const segB = partsB[i] ?? '0';\n\n // Try numeric comparison first\n const numA = parseInt(segA, 10);\n const numB = parseInt(segB, 10);\n\n if (!isNaN(numA) && !isNaN(numB)) {\n if (numA !== numB) return numA - numB;\n // If numeric parts are equal but segments differ (e.g. \"3-beta\" vs \"3\"),\n // compare the remaining suffix\n const suffixA = segA.slice(String(numA).length);\n const suffixB = segB.slice(String(numB).length);\n if (suffixA !== suffixB) {\n // Pre-release suffixes (starting with -) are lower than no suffix\n if (suffixA && !suffixB) return -1;\n if (!suffixA && suffixB) return 1;\n return suffixA.localeCompare(suffixB);\n }\n } else {\n // Lexicographic fallback for non-numeric segments\n const cmp = segA.localeCompare(segB);\n if (cmp !== 0) return cmp;\n }\n }\n\n return 0;\n}\n\n/**\n * Get the effective version string for comparison purposes.\n * Prefers resolvedVersion over declaredConstraint.\n */\nfunction getEffectiveVersion(dep: ParsedDependency): string {\n return dep.resolvedVersion ?? dep.declaredConstraint;\n}\n\n// \u2500\u2500 Deduplication \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * A deduplicated dependency entry combining data from multiple manifests.\n */\ninterface DeduplicatedDependency {\n name: string;\n ecosystem: string;\n /** The highest declared constraint across all manifests */\n declaredConstraint: string;\n /** The highest resolved version across all manifests (if any) */\n resolvedVersion?: string;\n /** Scope from the manifest with the highest version */\n scope: ParsedDependency['scope'];\n /** All source manifests that declared this dependency */\n sourceManifests: string[];\n /** License from manifest, if available */\n license?: string;\n}\n\n/**\n * Deduplicate dependencies by (name, ecosystem) pair, keeping the entry\n * with the highest version and collecting all source manifests.\n */\nexport function deduplicateDependencies(deps: ParsedDependency[]): DeduplicatedDependency[] {\n const map = new Map<string, DeduplicatedDependency>();\n\n for (const dep of deps) {\n const key = `${dep.ecosystem}:${dep.name}`;\n const existing = map.get(key);\n\n if (!existing) {\n map.set(key, {\n name: dep.name,\n ecosystem: dep.ecosystem,\n declaredConstraint: dep.declaredConstraint,\n resolvedVersion: dep.resolvedVersion,\n scope: dep.scope,\n sourceManifests: [dep.sourceManifest],\n license: dep.license,\n });\n } else {\n // Add source manifest if not already present\n if (!existing.sourceManifests.includes(dep.sourceManifest)) {\n existing.sourceManifests.push(dep.sourceManifest);\n }\n\n // Keep the highest version\n const existingVersion = existing.resolvedVersion ?? existing.declaredConstraint;\n const newVersion = getEffectiveVersion(dep);\n\n if (compareVersions(newVersion, existingVersion) > 0) {\n existing.declaredConstraint = dep.declaredConstraint;\n existing.resolvedVersion = dep.resolvedVersion;\n existing.scope = dep.scope;\n // Update license if the winning version entry has one\n if (dep.license !== undefined) {\n existing.license = dep.license;\n }\n } else if (existing.license === undefined && dep.license !== undefined) {\n // Even if version didn't win, adopt the license if we don't have one\n existing.license = dep.license;\n }\n }\n }\n\n return [...map.values()];\n}\n\n// \u2500\u2500 ManifestParser Class \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * ManifestParser orchestrates manifest discovery, parsing, deduplication,\n * and database persistence for the security module.\n */\nexport class ManifestParser {\n private readonly adapter: SecurityManifestAdapter;\n private readonly db: GraphDatabase;\n private readonly projectRoot: string;\n\n constructor(db: GraphDatabase, projectRoot: string) {\n this.db = db;\n this.projectRoot = projectRoot;\n this.adapter = new SecurityManifestAdapter(projectRoot);\n\n // Wrapped plugins (arch parser exists \u2014 ecosystem must match archParser.name)\n this.adapter.registerPlugin(createNpmPlugin());\n this.adapter.registerPlugin(createMavenPlugin());\n this.adapter.registerPlugin(createGoPlugin());\n this.adapter.registerPlugin(createPipPlugin());\n this.adapter.registerPlugin(createCargoPlugin());\n this.adapter.registerPlugin(createNugetPlugin());\n this.adapter.registerPlugin(createGradlePlugin());\n\n // Standalone plugins (no arch parser \u2014 own manifest discovery via manifestFiles)\n this.adapter.registerStandalonePlugin(createPyprojectPlugin());\n this.adapter.registerStandalonePlugin(createRubygemsPlugin());\n this.adapter.registerStandalonePlugin(createComposerPlugin());\n this.adapter.registerStandalonePlugin(createSwiftPlugin());\n this.adapter.registerStandalonePlugin(createPubspecPlugin());\n this.adapter.registerStandalonePlugin(createHexPlugin());\n }\n\n /**\n * Get the underlying adapter (useful for testing).\n */\n getAdapter(): SecurityManifestAdapter {\n return this.adapter;\n }\n\n /**\n * Run full manifest discovery, parsing, deduplication, and database persistence.\n *\n * Steps:\n * 1. Discover manifest files via the adapter (reuses architecture parsers)\n * 2. Extract dependencies with version/scope data via registered plugins\n * 3. Deduplicate: same (name, ecosystem) \u2192 single entry with highest version\n * 4. Create Dependency_Nodes in the database (nodes + sec_dependencies tables)\n * 5. Create `declared_in` edges linking dependencies to their source manifests\n */\n async parseAll(): Promise<ManifestParseResult> {\n const warnings: Array<{ file: string; line?: number; message: string }> = [];\n const errors: Array<{ file: string; message: string }> = [];\n\n // Step 1 & 2: Discover and extract all dependencies\n const allDeps: ParsedDependency[] = [];\n const manifestPaths = this.adapter.discoverManifests();\n let manifestsParsed = 0;\n\n for (const manifestPath of manifestPaths) {\n try {\n const deps = await this.adapter.extractFromManifest(manifestPath);\n if (deps.length > 0) {\n allDeps.push(...deps);\n manifestsParsed++;\n } else {\n // Manifest was parsed but had no dependencies \u2014 still counts\n manifestsParsed++;\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const relPath = manifestPath.replace(this.projectRoot + '/', '').replace(/\\\\/g, '/');\n errors.push({ file: relPath, message });\n logError(`[sec:parser] Failed to parse manifest ${relPath}: ${message}`);\n }\n }\n\n if (allDeps.length === 0) {\n return {\n dependenciesCreated: 0,\n manifestsParsed,\n warnings,\n errors,\n };\n }\n\n // Step 3: Deduplicate by (name, ecosystem)\n const deduplicated = deduplicateDependencies(allDeps);\n\n // Step 4 & 5: Persist to database\n let dependenciesCreated = 0;\n const rawDb = this.db.getRawDb();\n\n for (const dep of deduplicated) {\n try {\n const nodeId = `dep:${dep.ecosystem}:${dep.name}`;\n\n // Create the node in the nodes table via upsertNode\n const node: Node = {\n id: nodeId,\n kind: 'dependency',\n name: dep.name,\n qualifiedName: `${dep.ecosystem}/${dep.name}`,\n filePath: dep.sourceManifests[0] ?? '',\n language: 'unknown',\n startLine: 0,\n endLine: 0,\n startColumn: 0,\n endColumn: 0,\n signature: dep.resolvedVersion ?? dep.declaredConstraint,\n isExported: false,\n isAsync: false,\n isStatic: false,\n isAbstract: false,\n updatedAt: Date.now(),\n };\n\n this.db.upsertNode(node);\n\n // Insert/update the sec_dependencies row\n rawDb.run(\n `INSERT OR REPLACE INTO sec_dependencies\n (node_id, ecosystem, package_name, declared_constraint, resolved_version, scope, source_manifests, license)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n nodeId,\n dep.ecosystem,\n dep.name,\n dep.declaredConstraint,\n dep.resolvedVersion ?? null,\n dep.scope,\n JSON.stringify(dep.sourceManifests),\n dep.license ?? null,\n ],\n );\n\n // Create `declared_in` edges from the dependency to each source manifest\n for (const manifest of dep.sourceManifests) {\n const edge: Edge = {\n source: nodeId,\n target: manifest,\n kind: 'declared_in',\n };\n this.db.insertEdge(edge);\n }\n\n dependenciesCreated++;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n warnings.push({\n file: dep.sourceManifests[0] ?? 'unknown',\n message: `Failed to persist dependency ${dep.ecosystem}/${dep.name}: ${message}`,\n });\n logWarn(`[sec:parser] Failed to persist dependency ${dep.ecosystem}/${dep.name}: ${message}`);\n }\n }\n\n return {\n dependenciesCreated,\n manifestsParsed,\n warnings,\n errors,\n };\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_vitest = require("vitest");
|
|
3
|
+
var import_parser = require("./parser");
|
|
4
|
+
(0, import_vitest.describe)("compareVersions", () => {
|
|
5
|
+
(0, import_vitest.it)("should compare simple semver versions", () => {
|
|
6
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("1.0.0", "2.0.0")).toBeLessThan(0);
|
|
7
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("2.0.0", "1.0.0")).toBeGreaterThan(0);
|
|
8
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("1.0.0", "1.0.0")).toBe(0);
|
|
9
|
+
});
|
|
10
|
+
(0, import_vitest.it)("should compare versions with different patch levels", () => {
|
|
11
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("1.2.3", "1.2.4")).toBeLessThan(0);
|
|
12
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("1.2.10", "1.2.9")).toBeGreaterThan(0);
|
|
13
|
+
});
|
|
14
|
+
(0, import_vitest.it)("should compare versions with different minor levels", () => {
|
|
15
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("1.1.0", "1.2.0")).toBeLessThan(0);
|
|
16
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("1.10.0", "1.9.0")).toBeGreaterThan(0);
|
|
17
|
+
});
|
|
18
|
+
(0, import_vitest.it)("should handle versions with leading v", () => {
|
|
19
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("v1.2.3", "v1.2.4")).toBeLessThan(0);
|
|
20
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("v2.0.0", "1.0.0")).toBeGreaterThan(0);
|
|
21
|
+
});
|
|
22
|
+
(0, import_vitest.it)("should handle constraint prefixes (^, ~, >=)", () => {
|
|
23
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("^1.2.3", "^1.2.4")).toBeLessThan(0);
|
|
24
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("~2.0.0", "~1.0.0")).toBeGreaterThan(0);
|
|
25
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)(">=1.0.0", ">=2.0.0")).toBeLessThan(0);
|
|
26
|
+
});
|
|
27
|
+
(0, import_vitest.it)("should handle versions with different segment counts", () => {
|
|
28
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("1.2", "1.2.1")).toBeLessThan(0);
|
|
29
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("1.2.0", "1.2")).toBe(0);
|
|
30
|
+
});
|
|
31
|
+
(0, import_vitest.it)("should handle wildcard constraint as lowest", () => {
|
|
32
|
+
(0, import_vitest.expect)((0, import_parser.compareVersions)("1.0.0", "*")).toBeGreaterThan(0);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
(0, import_vitest.describe)("deduplicateDependencies", () => {
|
|
36
|
+
(0, import_vitest.it)("should return unique dependencies when no duplicates exist", () => {
|
|
37
|
+
const deps = [
|
|
38
|
+
{ name: "express", declaredConstraint: "^4.18.0", resolvedVersion: "4.18.2", scope: "production", ecosystem: "npm", sourceManifest: "package.json" },
|
|
39
|
+
{ name: "lodash", declaredConstraint: "^4.17.0", resolvedVersion: "4.17.21", scope: "production", ecosystem: "npm", sourceManifest: "package.json" }
|
|
40
|
+
];
|
|
41
|
+
const result = (0, import_parser.deduplicateDependencies)(deps);
|
|
42
|
+
(0, import_vitest.expect)(result).toHaveLength(2);
|
|
43
|
+
});
|
|
44
|
+
(0, import_vitest.it)("should deduplicate same (name, ecosystem) keeping highest version", () => {
|
|
45
|
+
const deps = [
|
|
46
|
+
{ name: "express", declaredConstraint: "^4.17.0", resolvedVersion: "4.17.1", scope: "production", ecosystem: "npm", sourceManifest: "packages/a/package.json" },
|
|
47
|
+
{ name: "express", declaredConstraint: "^4.18.0", resolvedVersion: "4.18.2", scope: "production", ecosystem: "npm", sourceManifest: "packages/b/package.json" }
|
|
48
|
+
];
|
|
49
|
+
const result = (0, import_parser.deduplicateDependencies)(deps);
|
|
50
|
+
(0, import_vitest.expect)(result).toHaveLength(1);
|
|
51
|
+
(0, import_vitest.expect)(result[0].name).toBe("express");
|
|
52
|
+
(0, import_vitest.expect)(result[0].resolvedVersion).toBe("4.18.2");
|
|
53
|
+
(0, import_vitest.expect)(result[0].declaredConstraint).toBe("^4.18.0");
|
|
54
|
+
(0, import_vitest.expect)(result[0].sourceManifests).toEqual(["packages/a/package.json", "packages/b/package.json"]);
|
|
55
|
+
});
|
|
56
|
+
(0, import_vitest.it)("should keep both when same name but different ecosystems", () => {
|
|
57
|
+
const deps = [
|
|
58
|
+
{ name: "serde", declaredConstraint: "1.0.0", resolvedVersion: "1.0.0", scope: "production", ecosystem: "cargo", sourceManifest: "Cargo.toml" },
|
|
59
|
+
{ name: "serde", declaredConstraint: "1.0.0", resolvedVersion: "1.0.0", scope: "production", ecosystem: "npm", sourceManifest: "package.json" }
|
|
60
|
+
];
|
|
61
|
+
const result = (0, import_parser.deduplicateDependencies)(deps);
|
|
62
|
+
(0, import_vitest.expect)(result).toHaveLength(2);
|
|
63
|
+
});
|
|
64
|
+
(0, import_vitest.it)("should collect all source manifests for duplicates", () => {
|
|
65
|
+
const deps = [
|
|
66
|
+
{ name: "lodash", declaredConstraint: "^4.17.0", resolvedVersion: "4.17.21", scope: "production", ecosystem: "npm", sourceManifest: "package.json" },
|
|
67
|
+
{ name: "lodash", declaredConstraint: "^4.17.0", resolvedVersion: "4.17.21", scope: "development", ecosystem: "npm", sourceManifest: "packages/lib/package.json" },
|
|
68
|
+
{ name: "lodash", declaredConstraint: "^4.17.0", resolvedVersion: "4.17.21", scope: "production", ecosystem: "npm", sourceManifest: "packages/app/package.json" }
|
|
69
|
+
];
|
|
70
|
+
const result = (0, import_parser.deduplicateDependencies)(deps);
|
|
71
|
+
(0, import_vitest.expect)(result).toHaveLength(1);
|
|
72
|
+
(0, import_vitest.expect)(result[0].sourceManifests).toHaveLength(3);
|
|
73
|
+
(0, import_vitest.expect)(result[0].sourceManifests).toContain("package.json");
|
|
74
|
+
(0, import_vitest.expect)(result[0].sourceManifests).toContain("packages/lib/package.json");
|
|
75
|
+
(0, import_vitest.expect)(result[0].sourceManifests).toContain("packages/app/package.json");
|
|
76
|
+
});
|
|
77
|
+
(0, import_vitest.it)("should not duplicate source manifests when same manifest appears twice", () => {
|
|
78
|
+
const deps = [
|
|
79
|
+
{ name: "express", declaredConstraint: "^4.17.0", scope: "production", ecosystem: "npm", sourceManifest: "package.json" },
|
|
80
|
+
{ name: "express", declaredConstraint: "^4.18.0", scope: "production", ecosystem: "npm", sourceManifest: "package.json" }
|
|
81
|
+
];
|
|
82
|
+
const result = (0, import_parser.deduplicateDependencies)(deps);
|
|
83
|
+
(0, import_vitest.expect)(result).toHaveLength(1);
|
|
84
|
+
(0, import_vitest.expect)(result[0].sourceManifests).toEqual(["package.json"]);
|
|
85
|
+
});
|
|
86
|
+
(0, import_vitest.it)("should use declaredConstraint for comparison when resolvedVersion is missing", () => {
|
|
87
|
+
const deps = [
|
|
88
|
+
{ name: "django", declaredConstraint: "3.2.0", scope: "production", ecosystem: "python", sourceManifest: "requirements.txt" },
|
|
89
|
+
{ name: "django", declaredConstraint: "4.2.0", scope: "production", ecosystem: "python", sourceManifest: "packages/api/requirements.txt" }
|
|
90
|
+
];
|
|
91
|
+
const result = (0, import_parser.deduplicateDependencies)(deps);
|
|
92
|
+
(0, import_vitest.expect)(result).toHaveLength(1);
|
|
93
|
+
(0, import_vitest.expect)(result[0].declaredConstraint).toBe("4.2.0");
|
|
94
|
+
});
|
|
95
|
+
(0, import_vitest.it)("should handle empty input", () => {
|
|
96
|
+
const result = (0, import_parser.deduplicateDependencies)([]);
|
|
97
|
+
(0, import_vitest.expect)(result).toHaveLength(0);
|
|
98
|
+
});
|
|
99
|
+
(0, import_vitest.it)("should prefer resolvedVersion over declaredConstraint for comparison", () => {
|
|
100
|
+
const deps = [
|
|
101
|
+
{ name: "express", declaredConstraint: "^4.0.0", resolvedVersion: "4.18.2", scope: "production", ecosystem: "npm", sourceManifest: "a/package.json" },
|
|
102
|
+
{ name: "express", declaredConstraint: "^5.0.0", resolvedVersion: "5.0.0", scope: "production", ecosystem: "npm", sourceManifest: "b/package.json" }
|
|
103
|
+
];
|
|
104
|
+
const result = (0, import_parser.deduplicateDependencies)(deps);
|
|
105
|
+
(0, import_vitest.expect)(result).toHaveLength(1);
|
|
106
|
+
(0, import_vitest.expect)(result[0].resolvedVersion).toBe("5.0.0");
|
|
107
|
+
(0, import_vitest.expect)(result[0].declaredConstraint).toBe("^5.0.0");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=parser.test.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/security/manifest/parser.test.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Unit tests for ManifestParser orchestrator\n */\nimport { describe, it, expect } from 'vitest';\nimport { compareVersions, deduplicateDependencies } from './parser';\nimport type { ParsedDependency } from '../types';\n\ndescribe('compareVersions', () => {\n it('should compare simple semver versions', () => {\n expect(compareVersions('1.0.0', '2.0.0')).toBeLessThan(0);\n expect(compareVersions('2.0.0', '1.0.0')).toBeGreaterThan(0);\n expect(compareVersions('1.0.0', '1.0.0')).toBe(0);\n });\n\n it('should compare versions with different patch levels', () => {\n expect(compareVersions('1.2.3', '1.2.4')).toBeLessThan(0);\n expect(compareVersions('1.2.10', '1.2.9')).toBeGreaterThan(0);\n });\n\n it('should compare versions with different minor levels', () => {\n expect(compareVersions('1.1.0', '1.2.0')).toBeLessThan(0);\n expect(compareVersions('1.10.0', '1.9.0')).toBeGreaterThan(0);\n });\n\n it('should handle versions with leading v', () => {\n expect(compareVersions('v1.2.3', 'v1.2.4')).toBeLessThan(0);\n expect(compareVersions('v2.0.0', '1.0.0')).toBeGreaterThan(0);\n });\n\n it('should handle constraint prefixes (^, ~, >=)', () => {\n expect(compareVersions('^1.2.3', '^1.2.4')).toBeLessThan(0);\n expect(compareVersions('~2.0.0', '~1.0.0')).toBeGreaterThan(0);\n expect(compareVersions('>=1.0.0', '>=2.0.0')).toBeLessThan(0);\n });\n\n it('should handle versions with different segment counts', () => {\n expect(compareVersions('1.2', '1.2.1')).toBeLessThan(0);\n expect(compareVersions('1.2.0', '1.2')).toBe(0);\n });\n\n it('should handle wildcard constraint as lowest', () => {\n // '*' is not numeric, so it falls to lexicographic comparison\n // but in practice we compare effective versions\n expect(compareVersions('1.0.0', '*')).toBeGreaterThan(0);\n });\n});\n\ndescribe('deduplicateDependencies', () => {\n it('should return unique dependencies when no duplicates exist', () => {\n const deps: ParsedDependency[] = [\n { name: 'express', declaredConstraint: '^4.18.0', resolvedVersion: '4.18.2', scope: 'production', ecosystem: 'npm', sourceManifest: 'package.json' },\n { name: 'lodash', declaredConstraint: '^4.17.0', resolvedVersion: '4.17.21', scope: 'production', ecosystem: 'npm', sourceManifest: 'package.json' },\n ];\n\n const result = deduplicateDependencies(deps);\n expect(result).toHaveLength(2);\n });\n\n it('should deduplicate same (name, ecosystem) keeping highest version', () => {\n const deps: ParsedDependency[] = [\n { name: 'express', declaredConstraint: '^4.17.0', resolvedVersion: '4.17.1', scope: 'production', ecosystem: 'npm', sourceManifest: 'packages/a/package.json' },\n { name: 'express', declaredConstraint: '^4.18.0', resolvedVersion: '4.18.2', scope: 'production', ecosystem: 'npm', sourceManifest: 'packages/b/package.json' },\n ];\n\n const result = deduplicateDependencies(deps);\n expect(result).toHaveLength(1);\n expect(result[0].name).toBe('express');\n expect(result[0].resolvedVersion).toBe('4.18.2');\n expect(result[0].declaredConstraint).toBe('^4.18.0');\n expect(result[0].sourceManifests).toEqual(['packages/a/package.json', 'packages/b/package.json']);\n });\n\n it('should keep both when same name but different ecosystems', () => {\n const deps: ParsedDependency[] = [\n { name: 'serde', declaredConstraint: '1.0.0', resolvedVersion: '1.0.0', scope: 'production', ecosystem: 'cargo', sourceManifest: 'Cargo.toml' },\n { name: 'serde', declaredConstraint: '1.0.0', resolvedVersion: '1.0.0', scope: 'production', ecosystem: 'npm', sourceManifest: 'package.json' },\n ];\n\n const result = deduplicateDependencies(deps);\n expect(result).toHaveLength(2);\n });\n\n it('should collect all source manifests for duplicates', () => {\n const deps: ParsedDependency[] = [\n { name: 'lodash', declaredConstraint: '^4.17.0', resolvedVersion: '4.17.21', scope: 'production', ecosystem: 'npm', sourceManifest: 'package.json' },\n { name: 'lodash', declaredConstraint: '^4.17.0', resolvedVersion: '4.17.21', scope: 'development', ecosystem: 'npm', sourceManifest: 'packages/lib/package.json' },\n { name: 'lodash', declaredConstraint: '^4.17.0', resolvedVersion: '4.17.21', scope: 'production', ecosystem: 'npm', sourceManifest: 'packages/app/package.json' },\n ];\n\n const result = deduplicateDependencies(deps);\n expect(result).toHaveLength(1);\n expect(result[0].sourceManifests).toHaveLength(3);\n expect(result[0].sourceManifests).toContain('package.json');\n expect(result[0].sourceManifests).toContain('packages/lib/package.json');\n expect(result[0].sourceManifests).toContain('packages/app/package.json');\n });\n\n it('should not duplicate source manifests when same manifest appears twice', () => {\n const deps: ParsedDependency[] = [\n { name: 'express', declaredConstraint: '^4.17.0', scope: 'production', ecosystem: 'npm', sourceManifest: 'package.json' },\n { name: 'express', declaredConstraint: '^4.18.0', scope: 'production', ecosystem: 'npm', sourceManifest: 'package.json' },\n ];\n\n const result = deduplicateDependencies(deps);\n expect(result).toHaveLength(1);\n expect(result[0].sourceManifests).toEqual(['package.json']);\n });\n\n it('should use declaredConstraint for comparison when resolvedVersion is missing', () => {\n const deps: ParsedDependency[] = [\n { name: 'django', declaredConstraint: '3.2.0', scope: 'production', ecosystem: 'python', sourceManifest: 'requirements.txt' },\n { name: 'django', declaredConstraint: '4.2.0', scope: 'production', ecosystem: 'python', sourceManifest: 'packages/api/requirements.txt' },\n ];\n\n const result = deduplicateDependencies(deps);\n expect(result).toHaveLength(1);\n expect(result[0].declaredConstraint).toBe('4.2.0');\n });\n\n it('should handle empty input', () => {\n const result = deduplicateDependencies([]);\n expect(result).toHaveLength(0);\n });\n\n it('should prefer resolvedVersion over declaredConstraint for comparison', () => {\n const deps: ParsedDependency[] = [\n { name: 'express', declaredConstraint: '^4.0.0', resolvedVersion: '4.18.2', scope: 'production', ecosystem: 'npm', sourceManifest: 'a/package.json' },\n { name: 'express', declaredConstraint: '^5.0.0', resolvedVersion: '5.0.0', scope: 'production', ecosystem: 'npm', sourceManifest: 'b/package.json' },\n ];\n\n const result = deduplicateDependencies(deps);\n expect(result).toHaveLength(1);\n expect(result[0].resolvedVersion).toBe('5.0.0');\n expect(result[0].declaredConstraint).toBe('^5.0.0');\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|