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,80 @@
|
|
|
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 bridges_exports = {};
|
|
20
|
+
__export(bridges_exports, {
|
|
21
|
+
runBridgeResolvers: () => runBridgeResolvers
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(bridges_exports);
|
|
24
|
+
var import_errors = require("../../errors");
|
|
25
|
+
var import_swift_objc = require("./swift-objc");
|
|
26
|
+
var import_react_native = require("./react-native");
|
|
27
|
+
var import_turbomodules = require("./turbomodules");
|
|
28
|
+
var import_expo_modules = require("./expo-modules");
|
|
29
|
+
var import_native_events = require("./native-events");
|
|
30
|
+
var import_native_views = require("./native-views");
|
|
31
|
+
var import_android_rn = require("./android-rn");
|
|
32
|
+
var import_flutter_channel = require("./flutter-channel");
|
|
33
|
+
const ALL_BRIDGES = [
|
|
34
|
+
import_swift_objc.swiftObjcBridge,
|
|
35
|
+
import_react_native.reactNativeLegacyBridge,
|
|
36
|
+
import_turbomodules.turboModulesBridge,
|
|
37
|
+
import_expo_modules.expoModulesBridge,
|
|
38
|
+
import_native_events.nativeEventsBridge,
|
|
39
|
+
import_native_views.nativeViewsBridge,
|
|
40
|
+
import_android_rn.androidRnBridge,
|
|
41
|
+
import_flutter_channel.flutterChannelBridge
|
|
42
|
+
];
|
|
43
|
+
function runBridgeResolvers(context, db) {
|
|
44
|
+
const start = Date.now();
|
|
45
|
+
const bridgesRun = [];
|
|
46
|
+
let totalEdges = 0;
|
|
47
|
+
for (const bridge of ALL_BRIDGES) {
|
|
48
|
+
try {
|
|
49
|
+
if (!bridge.detect(context)) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
(0, import_errors.logDebug)(`Bridge: running ${bridge.name}`);
|
|
53
|
+
const edges = bridge.resolve(context);
|
|
54
|
+
for (const synth of edges) {
|
|
55
|
+
const edge = {
|
|
56
|
+
source: synth.source,
|
|
57
|
+
target: synth.target,
|
|
58
|
+
kind: synth.kind,
|
|
59
|
+
confidence: synth.confidence,
|
|
60
|
+
confidenceScore: synth.confidenceScore,
|
|
61
|
+
metadata: synth.metadata
|
|
62
|
+
};
|
|
63
|
+
db.insertEdge(edge);
|
|
64
|
+
}
|
|
65
|
+
totalEdges += edges.length;
|
|
66
|
+
bridgesRun.push(bridge.name);
|
|
67
|
+
(0, import_errors.logDebug)(`Bridge: ${bridge.name} synthesized ${edges.length} edges`);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
(0, import_errors.logWarn)(`Bridge: ${bridge.name} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const durationMs = Date.now() - start;
|
|
73
|
+
(0, import_errors.logDebug)(`Bridge resolution complete: ${totalEdges} edges from ${bridgesRun.length} bridges in ${durationMs}ms`);
|
|
74
|
+
return { totalEdges, bridgesRun, durationMs };
|
|
75
|
+
}
|
|
76
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
77
|
+
0 && (module.exports = {
|
|
78
|
+
runBridgeResolvers
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/resolution/bridges/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Bridge Resolver Registry\n *\n * Manages cross-language bridge resolvers that synthesize edges between\n * symbols in different languages (Swift \u2194 ObjC, JS \u2194 Native, etc.).\n * Bridges run after standard resolution and emit heuristic-based edges.\n */\n\nimport type { Node, Edge, EdgeKind } from '../../types';\nimport type { ResolutionContext } from '../../frameworks/types';\nimport type { GraphDatabase } from '../../db/database';\nimport { logDebug, logWarn } from '../../errors';\n\n// \u2500\u2500 Types \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface SynthesizedEdge {\n source: string; // node ID\n target: string; // node ID\n kind: EdgeKind;\n confidence: 'inferred';\n confidenceScore: number;\n metadata: {\n synthesizedBy: string; // e.g. 'swift-objc-bridge'\n provenance: 'heuristic';\n [key: string]: unknown;\n };\n}\n\nexport interface BridgeResolver {\n name: string;\n /** Detect if this bridge is relevant for the project */\n detect(context: ResolutionContext): boolean;\n /** Synthesize cross-language edges */\n resolve(context: ResolutionContext): SynthesizedEdge[];\n}\n\n// \u2500\u2500 Bridge Registry \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\nimport { swiftObjcBridge } from './swift-objc';\nimport { reactNativeLegacyBridge } from './react-native';\nimport { turboModulesBridge } from './turbomodules';\nimport { expoModulesBridge } from './expo-modules';\nimport { nativeEventsBridge } from './native-events';\nimport { nativeViewsBridge } from './native-views';\nimport { androidRnBridge } from './android-rn';\nimport { flutterChannelBridge } from './flutter-channel';\n\nconst ALL_BRIDGES: BridgeResolver[] = [\n swiftObjcBridge,\n reactNativeLegacyBridge,\n turboModulesBridge,\n expoModulesBridge,\n nativeEventsBridge,\n nativeViewsBridge,\n androidRnBridge,\n flutterChannelBridge,\n];\n\n// \u2500\u2500 Public API \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\u2500\u2500\u2500\n\nexport interface BridgeResolutionResult {\n totalEdges: number;\n bridgesRun: string[];\n durationMs: number;\n}\n\n/**\n * Run all applicable bridge resolvers and insert synthesized edges into the database.\n * Bridges that are not relevant for the project are skipped via detect().\n */\nexport function runBridgeResolvers(\n context: ResolutionContext,\n db: GraphDatabase\n): BridgeResolutionResult {\n const start = Date.now();\n const bridgesRun: string[] = [];\n let totalEdges = 0;\n\n for (const bridge of ALL_BRIDGES) {\n try {\n if (!bridge.detect(context)) {\n continue;\n }\n\n logDebug(`Bridge: running ${bridge.name}`);\n const edges = bridge.resolve(context);\n\n for (const synth of edges) {\n const edge: Edge = {\n source: synth.source,\n target: synth.target,\n kind: synth.kind,\n confidence: synth.confidence,\n confidenceScore: synth.confidenceScore,\n metadata: synth.metadata,\n };\n db.insertEdge(edge);\n }\n\n totalEdges += edges.length;\n bridgesRun.push(bridge.name);\n logDebug(`Bridge: ${bridge.name} synthesized ${edges.length} edges`);\n } catch (err) {\n logWarn(`Bridge: ${bridge.name} failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n const durationMs = Date.now() - start;\n logDebug(`Bridge resolution complete: ${totalEdges} edges from ${bridgesRun.length} bridges in ${durationMs}ms`);\n\n return { totalEdges, bridgesRun, durationMs };\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,oBAAkC;AA2BlC,wBAAgC;AAChC,0BAAwC;AACxC,0BAAmC;AACnC,0BAAkC;AAClC,2BAAmC;AACnC,0BAAkC;AAClC,wBAAgC;AAChC,6BAAqC;AAErC,MAAM,cAAgC;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAcO,SAAS,mBACd,SACA,IACwB;AACxB,QAAM,QAAQ,KAAK,IAAI;AACvB,QAAM,aAAuB,CAAC;AAC9B,MAAI,aAAa;AAEjB,aAAW,UAAU,aAAa;AAChC,QAAI;AACF,UAAI,CAAC,OAAO,OAAO,OAAO,GAAG;AAC3B;AAAA,MACF;AAEA,kCAAS,mBAAmB,OAAO,IAAI,EAAE;AACzC,YAAM,QAAQ,OAAO,QAAQ,OAAO;AAEpC,iBAAW,SAAS,OAAO;AACzB,cAAM,OAAa;AAAA,UACjB,QAAQ,MAAM;AAAA,UACd,QAAQ,MAAM;AAAA,UACd,MAAM,MAAM;AAAA,UACZ,YAAY,MAAM;AAAA,UAClB,iBAAiB,MAAM;AAAA,UACvB,UAAU,MAAM;AAAA,QAClB;AACA,WAAG,WAAW,IAAI;AAAA,MACpB;AAEA,oBAAc,MAAM;AACpB,iBAAW,KAAK,OAAO,IAAI;AAC3B,kCAAS,WAAW,OAAO,IAAI,gBAAgB,MAAM,MAAM,QAAQ;AAAA,IACrE,SAAS,KAAK;AACZ,iCAAQ,WAAW,OAAO,IAAI,YAAY,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,IAC9F;AAAA,EACF;AAEA,QAAM,aAAa,KAAK,IAAI,IAAI;AAChC,8BAAS,+BAA+B,UAAU,eAAe,WAAW,MAAM,eAAe,UAAU,IAAI;AAE/G,SAAO,EAAE,YAAY,YAAY,WAAW;AAC9C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
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 native_events_exports = {};
|
|
20
|
+
__export(native_events_exports, {
|
|
21
|
+
nativeEventsBridge: () => nativeEventsBridge
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(native_events_exports);
|
|
24
|
+
function findEventListeners(context) {
|
|
25
|
+
const listeners = [];
|
|
26
|
+
const files = context.getAllFiles();
|
|
27
|
+
for (const f of files) {
|
|
28
|
+
if (!f.endsWith(".ts") && !f.endsWith(".tsx") && !f.endsWith(".js") && !f.endsWith(".jsx")) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const content = context.readFile(f);
|
|
32
|
+
if (!content) continue;
|
|
33
|
+
const nodes = context.getNodesInFile(f);
|
|
34
|
+
const addListenerRegex = /\.addListener\s*\(\s*['"]([^'"]+)['"]/g;
|
|
35
|
+
let match;
|
|
36
|
+
while ((match = addListenerRegex.exec(content)) !== null) {
|
|
37
|
+
const eventName = match[1];
|
|
38
|
+
const lineNum = content.slice(0, match.index).split("\n").length;
|
|
39
|
+
const enclosing = nodes.find(
|
|
40
|
+
(n) => (n.kind === "function" || n.kind === "method") && n.startLine <= lineNum && n.endLine >= lineNum
|
|
41
|
+
);
|
|
42
|
+
if (enclosing) {
|
|
43
|
+
listeners.push({ eventName, listenerNodeId: enclosing.id, filePath: f });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const deviceEmitterRegex = /DeviceEventEmitter\.addListener\s*\(\s*['"]([^'"]+)['"]/g;
|
|
47
|
+
while ((match = deviceEmitterRegex.exec(content)) !== null) {
|
|
48
|
+
const eventName = match[1];
|
|
49
|
+
const lineNum = content.slice(0, match.index).split("\n").length;
|
|
50
|
+
const enclosing = nodes.find(
|
|
51
|
+
(n) => (n.kind === "function" || n.kind === "method") && n.startLine <= lineNum && n.endLine >= lineNum
|
|
52
|
+
);
|
|
53
|
+
if (enclosing) {
|
|
54
|
+
listeners.push({ eventName, listenerNodeId: enclosing.id, filePath: f });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const subscriptionRegex = /(?:on|subscribe|addEventListener)\s*\(\s*['"]([^'"]+)['"]/g;
|
|
58
|
+
while ((match = subscriptionRegex.exec(content)) !== null) {
|
|
59
|
+
const eventName = match[1];
|
|
60
|
+
const lineNum = content.slice(0, match.index).split("\n").length;
|
|
61
|
+
const enclosing = nodes.find(
|
|
62
|
+
(n) => (n.kind === "function" || n.kind === "method") && n.startLine <= lineNum && n.endLine >= lineNum
|
|
63
|
+
);
|
|
64
|
+
if (enclosing) {
|
|
65
|
+
listeners.push({ eventName, listenerNodeId: enclosing.id, filePath: f });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return listeners;
|
|
70
|
+
}
|
|
71
|
+
function findEventEmitters(context) {
|
|
72
|
+
const emitters = [];
|
|
73
|
+
const files = context.getAllFiles();
|
|
74
|
+
for (const f of files) {
|
|
75
|
+
if (f.endsWith(".m") || f.endsWith(".mm")) {
|
|
76
|
+
const content = context.readFile(f);
|
|
77
|
+
if (!content) continue;
|
|
78
|
+
const nodes = context.getNodesInFile(f);
|
|
79
|
+
const sendEventRegex = /sendEventWithName\s*:\s*@"([^"]+)"/g;
|
|
80
|
+
let match;
|
|
81
|
+
while ((match = sendEventRegex.exec(content)) !== null) {
|
|
82
|
+
const eventName = match[1];
|
|
83
|
+
const lineNum = content.slice(0, match.index).split("\n").length;
|
|
84
|
+
const enclosing = nodes.find(
|
|
85
|
+
(n) => (n.kind === "method" || n.kind === "function") && n.startLine <= lineNum && n.endLine >= lineNum
|
|
86
|
+
);
|
|
87
|
+
if (enclosing) {
|
|
88
|
+
emitters.push({ eventName, emitterNodeId: enclosing.id, filePath: f, language: "objc" });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (f.endsWith(".swift")) {
|
|
93
|
+
const content = context.readFile(f);
|
|
94
|
+
if (!content) continue;
|
|
95
|
+
const nodes = context.getNodesInFile(f);
|
|
96
|
+
const sendEventRegex = /sendEvent\s*\(\s*withName\s*:\s*"([^"]+)"/g;
|
|
97
|
+
let match;
|
|
98
|
+
while ((match = sendEventRegex.exec(content)) !== null) {
|
|
99
|
+
const eventName = match[1];
|
|
100
|
+
const lineNum = content.slice(0, match.index).split("\n").length;
|
|
101
|
+
const enclosing = nodes.find(
|
|
102
|
+
(n) => (n.kind === "method" || n.kind === "function") && n.startLine <= lineNum && n.endLine >= lineNum
|
|
103
|
+
);
|
|
104
|
+
if (enclosing) {
|
|
105
|
+
emitters.push({ eventName, emitterNodeId: enclosing.id, filePath: f, language: "swift" });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const expoSendRegex = /sendEvent\s*\(\s*"([^"]+)"/g;
|
|
109
|
+
while ((match = expoSendRegex.exec(content)) !== null) {
|
|
110
|
+
const eventName = match[1];
|
|
111
|
+
const lineNum = content.slice(0, match.index).split("\n").length;
|
|
112
|
+
const enclosing = nodes.find(
|
|
113
|
+
(n) => (n.kind === "method" || n.kind === "function") && n.startLine <= lineNum && n.endLine >= lineNum
|
|
114
|
+
);
|
|
115
|
+
if (enclosing) {
|
|
116
|
+
emitters.push({ eventName, emitterNodeId: enclosing.id, filePath: f, language: "swift" });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (f.endsWith(".java") || f.endsWith(".kt")) {
|
|
121
|
+
const content = context.readFile(f);
|
|
122
|
+
if (!content) continue;
|
|
123
|
+
const nodes = context.getNodesInFile(f);
|
|
124
|
+
const emitRegex = /(?:\.emit|sendEvent)\s*\(\s*"([^"]+)"/g;
|
|
125
|
+
let match;
|
|
126
|
+
while ((match = emitRegex.exec(content)) !== null) {
|
|
127
|
+
const eventName = match[1];
|
|
128
|
+
const lineNum = content.slice(0, match.index).split("\n").length;
|
|
129
|
+
const enclosing = nodes.find(
|
|
130
|
+
(n) => (n.kind === "method" || n.kind === "function") && n.startLine <= lineNum && n.endLine >= lineNum
|
|
131
|
+
);
|
|
132
|
+
if (enclosing) {
|
|
133
|
+
const lang = f.endsWith(".kt") ? "kotlin" : "java";
|
|
134
|
+
emitters.push({ eventName, emitterNodeId: enclosing.id, filePath: f, language: lang });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return emitters;
|
|
140
|
+
}
|
|
141
|
+
const nativeEventsBridge = {
|
|
142
|
+
name: "native-events-bridge",
|
|
143
|
+
detect(context) {
|
|
144
|
+
const files = context.getAllFiles();
|
|
145
|
+
for (const f of files) {
|
|
146
|
+
if (!f.endsWith(".ts") && !f.endsWith(".tsx") && !f.endsWith(".js") && !f.endsWith(".jsx")) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const content = context.readFile(f);
|
|
150
|
+
if (!content) continue;
|
|
151
|
+
if (content.includes("NativeEventEmitter") || content.includes("DeviceEventEmitter")) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return false;
|
|
156
|
+
},
|
|
157
|
+
resolve(context) {
|
|
158
|
+
const edges = [];
|
|
159
|
+
const listeners = findEventListeners(context);
|
|
160
|
+
const emitters = findEventEmitters(context);
|
|
161
|
+
for (const emitter of emitters) {
|
|
162
|
+
for (const listener of listeners) {
|
|
163
|
+
if (emitter.eventName === listener.eventName) {
|
|
164
|
+
edges.push({
|
|
165
|
+
source: emitter.emitterNodeId,
|
|
166
|
+
target: listener.listenerNodeId,
|
|
167
|
+
kind: "calls",
|
|
168
|
+
confidence: "inferred",
|
|
169
|
+
confidenceScore: 0.85,
|
|
170
|
+
metadata: {
|
|
171
|
+
synthesizedBy: "native-events-bridge",
|
|
172
|
+
provenance: "heuristic",
|
|
173
|
+
eventName: emitter.eventName,
|
|
174
|
+
direction: "native-to-js",
|
|
175
|
+
nativeLanguage: emitter.language
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return edges;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
185
|
+
0 && (module.exports = {
|
|
186
|
+
nativeEventsBridge
|
|
187
|
+
});
|
|
188
|
+
//# sourceMappingURL=native-events.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/resolution/bridges/native-events.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Native \u2192 JS Events Bridge\n *\n * Synthesizes edges between native event emitters (sendEventWithName: in ObjC,\n * .emit() in Java/Kotlin) and JavaScript event listeners (NativeEventEmitter.addListener).\n * Matches by literal event name string.\n */\n\nimport type { Node } from '../../types';\nimport type { ResolutionContext } from '../../frameworks/types';\nimport type { BridgeResolver, SynthesizedEdge } from './index';\n\n// \u2500\u2500 Helpers \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\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface EventListener {\n eventName: string;\n listenerNodeId: string;\n filePath: string;\n}\n\ninterface EventEmitter {\n eventName: string;\n emitterNodeId: string;\n filePath: string;\n language: 'objc' | 'java' | 'kotlin' | 'swift';\n}\n\n/**\n * Find JS/TS event listeners using NativeEventEmitter.addListener pattern.\n */\nfunction findEventListeners(context: ResolutionContext): EventListener[] {\n const listeners: EventListener[] = [];\n const files = context.getAllFiles();\n\n for (const f of files) {\n if (!f.endsWith('.ts') && !f.endsWith('.tsx') && !f.endsWith('.js') && !f.endsWith('.jsx')) {\n continue;\n }\n\n const content = context.readFile(f);\n if (!content) continue;\n\n const nodes = context.getNodesInFile(f);\n\n // Pattern 1: emitter.addListener('eventName', callback)\n const addListenerRegex = /\\.addListener\\s*\\(\\s*['\"]([^'\"]+)['\"]/g;\n let match: RegExpExecArray | null;\n\n while ((match = addListenerRegex.exec(content)) !== null) {\n const eventName = match[1];\n const lineNum = content.slice(0, match.index).split('\\n').length;\n\n const enclosing = nodes.find(\n n => (n.kind === 'function' || n.kind === 'method') &&\n n.startLine <= lineNum && n.endLine >= lineNum\n );\n\n if (enclosing) {\n listeners.push({ eventName, listenerNodeId: enclosing.id, filePath: f });\n }\n }\n\n // Pattern 2: DeviceEventEmitter.addListener('eventName', ...)\n const deviceEmitterRegex = /DeviceEventEmitter\\.addListener\\s*\\(\\s*['\"]([^'\"]+)['\"]/g;\n while ((match = deviceEmitterRegex.exec(content)) !== null) {\n const eventName = match[1];\n const lineNum = content.slice(0, match.index).split('\\n').length;\n\n const enclosing = nodes.find(\n n => (n.kind === 'function' || n.kind === 'method') &&\n n.startLine <= lineNum && n.endLine >= lineNum\n );\n\n if (enclosing) {\n listeners.push({ eventName, listenerNodeId: enclosing.id, filePath: f });\n }\n }\n\n // Pattern 3: useEffect with subscription pattern\n const subscriptionRegex = /(?:on|subscribe|addEventListener)\\s*\\(\\s*['\"]([^'\"]+)['\"]/g;\n while ((match = subscriptionRegex.exec(content)) !== null) {\n const eventName = match[1];\n const lineNum = content.slice(0, match.index).split('\\n').length;\n\n const enclosing = nodes.find(\n n => (n.kind === 'function' || n.kind === 'method') &&\n n.startLine <= lineNum && n.endLine >= lineNum\n );\n\n if (enclosing) {\n listeners.push({ eventName, listenerNodeId: enclosing.id, filePath: f });\n }\n }\n }\n\n return listeners;\n}\n\n/**\n * Find native event emitters in ObjC/Swift/Java/Kotlin files.\n */\nfunction findEventEmitters(context: ResolutionContext): EventEmitter[] {\n const emitters: EventEmitter[] = [];\n const files = context.getAllFiles();\n\n for (const f of files) {\n // ObjC files\n if (f.endsWith('.m') || f.endsWith('.mm')) {\n const content = context.readFile(f);\n if (!content) continue;\n\n const nodes = context.getNodesInFile(f);\n\n // Pattern: sendEventWithName:@\"eventName\"\n const sendEventRegex = /sendEventWithName\\s*:\\s*@\"([^\"]+)\"/g;\n let match: RegExpExecArray | null;\n\n while ((match = sendEventRegex.exec(content)) !== null) {\n const eventName = match[1];\n const lineNum = content.slice(0, match.index).split('\\n').length;\n\n const enclosing = nodes.find(\n n => (n.kind === 'method' || n.kind === 'function') &&\n n.startLine <= lineNum && n.endLine >= lineNum\n );\n\n if (enclosing) {\n emitters.push({ eventName, emitterNodeId: enclosing.id, filePath: f, language: 'objc' });\n }\n }\n }\n\n // Swift files\n if (f.endsWith('.swift')) {\n const content = context.readFile(f);\n if (!content) continue;\n\n const nodes = context.getNodesInFile(f);\n\n // Pattern: sendEvent(withName: \"eventName\", ...)\n const sendEventRegex = /sendEvent\\s*\\(\\s*withName\\s*:\\s*\"([^\"]+)\"/g;\n let match: RegExpExecArray | null;\n\n while ((match = sendEventRegex.exec(content)) !== null) {\n const eventName = match[1];\n const lineNum = content.slice(0, match.index).split('\\n').length;\n\n const enclosing = nodes.find(\n n => (n.kind === 'method' || n.kind === 'function') &&\n n.startLine <= lineNum && n.endLine >= lineNum\n );\n\n if (enclosing) {\n emitters.push({ eventName, emitterNodeId: enclosing.id, filePath: f, language: 'swift' });\n }\n }\n\n // Expo pattern: sendEvent(\"eventName\", ...)\n const expoSendRegex = /sendEvent\\s*\\(\\s*\"([^\"]+)\"/g;\n while ((match = expoSendRegex.exec(content)) !== null) {\n const eventName = match[1];\n const lineNum = content.slice(0, match.index).split('\\n').length;\n\n const enclosing = nodes.find(\n n => (n.kind === 'method' || n.kind === 'function') &&\n n.startLine <= lineNum && n.endLine >= lineNum\n );\n\n if (enclosing) {\n emitters.push({ eventName, emitterNodeId: enclosing.id, filePath: f, language: 'swift' });\n }\n }\n }\n\n // Java/Kotlin files\n if (f.endsWith('.java') || f.endsWith('.kt')) {\n const content = context.readFile(f);\n if (!content) continue;\n\n const nodes = context.getNodesInFile(f);\n\n // Pattern: .emit(\"eventName\", ...) or sendEvent(\"eventName\", ...)\n const emitRegex = /(?:\\.emit|sendEvent)\\s*\\(\\s*\"([^\"]+)\"/g;\n let match: RegExpExecArray | null;\n\n while ((match = emitRegex.exec(content)) !== null) {\n const eventName = match[1];\n const lineNum = content.slice(0, match.index).split('\\n').length;\n\n const enclosing = nodes.find(\n n => (n.kind === 'method' || n.kind === 'function') &&\n n.startLine <= lineNum && n.endLine >= lineNum\n );\n\n if (enclosing) {\n const lang = f.endsWith('.kt') ? 'kotlin' as const : 'java' as const;\n emitters.push({ eventName, emitterNodeId: enclosing.id, filePath: f, language: lang });\n }\n }\n }\n }\n\n return emitters;\n}\n\n// \u2500\u2500 Bridge Implementation \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\nexport const nativeEventsBridge: BridgeResolver = {\n name: 'native-events-bridge',\n\n detect(context: ResolutionContext): boolean {\n const files = context.getAllFiles();\n\n for (const f of files) {\n if (!f.endsWith('.ts') && !f.endsWith('.tsx') && !f.endsWith('.js') && !f.endsWith('.jsx')) {\n continue;\n }\n\n const content = context.readFile(f);\n if (!content) continue;\n\n // Check for NativeEventEmitter or DeviceEventEmitter usage\n if (content.includes('NativeEventEmitter') || content.includes('DeviceEventEmitter')) {\n return true;\n }\n }\n\n return false;\n },\n\n resolve(context: ResolutionContext): SynthesizedEdge[] {\n const edges: SynthesizedEdge[] = [];\n\n const listeners = findEventListeners(context);\n const emitters = findEventEmitters(context);\n\n // Match emitters to listeners by event name\n // Direction: native emitter \u2192 JS listener (native calls into JS)\n for (const emitter of emitters) {\n for (const listener of listeners) {\n if (emitter.eventName === listener.eventName) {\n edges.push({\n source: emitter.emitterNodeId,\n target: listener.listenerNodeId,\n kind: 'calls',\n confidence: 'inferred',\n confidenceScore: 0.85,\n metadata: {\n synthesizedBy: 'native-events-bridge',\n provenance: 'heuristic',\n eventName: emitter.eventName,\n direction: 'native-to-js',\n nativeLanguage: emitter.language,\n },\n });\n }\n }\n }\n\n return edges;\n },\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
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 native_views_exports = {};
|
|
20
|
+
__export(native_views_exports, {
|
|
21
|
+
nativeViewsBridge: () => nativeViewsBridge
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(native_views_exports);
|
|
24
|
+
const VIEW_MANAGER_SUFFIXES = [
|
|
25
|
+
"Manager",
|
|
26
|
+
"ViewManager",
|
|
27
|
+
"ComponentView",
|
|
28
|
+
"NativeComponent"
|
|
29
|
+
];
|
|
30
|
+
const VIEW_MANAGER_PREFIXES = ["RCT", ""];
|
|
31
|
+
function findNativeViewUsages(context) {
|
|
32
|
+
const usages = [];
|
|
33
|
+
const files = context.getAllFiles();
|
|
34
|
+
for (const f of files) {
|
|
35
|
+
if (!f.endsWith(".tsx") && !f.endsWith(".jsx")) continue;
|
|
36
|
+
const content = context.readFile(f);
|
|
37
|
+
if (!content) continue;
|
|
38
|
+
const nodes = context.getNodesInFile(f);
|
|
39
|
+
const requireNativeRegex = /requireNativeComponent\s*(?:<[^>]*>)?\s*\(\s*['"](\w+)['"]\s*\)/g;
|
|
40
|
+
let match;
|
|
41
|
+
while ((match = requireNativeRegex.exec(content)) !== null) {
|
|
42
|
+
const componentName = match[1];
|
|
43
|
+
const lineNum = content.slice(0, match.index).split("\n").length;
|
|
44
|
+
const enclosing = nodes.find(
|
|
45
|
+
(n) => n.startLine <= lineNum && n.endLine >= lineNum
|
|
46
|
+
);
|
|
47
|
+
if (enclosing) {
|
|
48
|
+
usages.push({ componentName, usageNodeId: enclosing.id, filePath: f });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const codegenRegex = /codegenNativeComponent\s*(?:<[^>]*>)?\s*\(\s*['"](\w+)['"]\s*\)/g;
|
|
52
|
+
while ((match = codegenRegex.exec(content)) !== null) {
|
|
53
|
+
const componentName = match[1];
|
|
54
|
+
const lineNum = content.slice(0, match.index).split("\n").length;
|
|
55
|
+
const enclosing = nodes.find(
|
|
56
|
+
(n) => n.startLine <= lineNum && n.endLine >= lineNum
|
|
57
|
+
);
|
|
58
|
+
if (enclosing) {
|
|
59
|
+
usages.push({ componentName, usageNodeId: enclosing.id, filePath: f });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const uiManagerRegex = /UIManager\.getViewManagerConfig\s*\(\s*['"](\w+)['"]\s*\)/g;
|
|
63
|
+
while ((match = uiManagerRegex.exec(content)) !== null) {
|
|
64
|
+
const componentName = match[1];
|
|
65
|
+
const lineNum = content.slice(0, match.index).split("\n").length;
|
|
66
|
+
const enclosing = nodes.find(
|
|
67
|
+
(n) => n.startLine <= lineNum && n.endLine >= lineNum
|
|
68
|
+
);
|
|
69
|
+
if (enclosing) {
|
|
70
|
+
usages.push({ componentName, usageNodeId: enclosing.id, filePath: f });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return usages;
|
|
75
|
+
}
|
|
76
|
+
function findNativeViewManagers(context) {
|
|
77
|
+
const managers = [];
|
|
78
|
+
const files = context.getAllFiles();
|
|
79
|
+
for (const f of files) {
|
|
80
|
+
if (!f.endsWith(".m") && !f.endsWith(".mm") && !f.endsWith(".swift") && !f.endsWith(".java") && !f.endsWith(".kt") && !f.endsWith(".h")) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const content = context.readFile(f);
|
|
84
|
+
if (!content) continue;
|
|
85
|
+
const nodes = context.getNodesInFile(f);
|
|
86
|
+
if (f.endsWith(".m") || f.endsWith(".mm") || f.endsWith(".h")) {
|
|
87
|
+
const implRegex = /@(?:implementation|interface)\s+(\w+(?:Manager|ViewManager|ComponentView))\b/g;
|
|
88
|
+
let match;
|
|
89
|
+
while ((match = implRegex.exec(content)) !== null) {
|
|
90
|
+
const className = match[1];
|
|
91
|
+
const componentName = extractComponentName(className);
|
|
92
|
+
const classNode = nodes.find(
|
|
93
|
+
(n) => n.kind === "class" && n.name === className
|
|
94
|
+
);
|
|
95
|
+
if (classNode && componentName) {
|
|
96
|
+
managers.push({ componentName, nodeId: classNode.id, filePath: f, className });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (content.includes("RCT_EXPORT_VIEW_PROPERTY") || content.includes("RCTViewManager")) {
|
|
100
|
+
const classImpl = content.match(/@implementation\s+(\w+)/);
|
|
101
|
+
if (classImpl) {
|
|
102
|
+
const className = classImpl[1];
|
|
103
|
+
const componentName = extractComponentName(className);
|
|
104
|
+
const classNode = nodes.find((n) => n.kind === "class" && n.name === className);
|
|
105
|
+
if (classNode && componentName) {
|
|
106
|
+
const exists = managers.some((m) => m.nodeId === classNode.id);
|
|
107
|
+
if (!exists) {
|
|
108
|
+
managers.push({ componentName, nodeId: classNode.id, filePath: f, className });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (f.endsWith(".swift")) {
|
|
115
|
+
const classRegex = /class\s+(\w+(?:Manager|ViewManager|ComponentView))\s*:\s*(\w+)/g;
|
|
116
|
+
let match;
|
|
117
|
+
while ((match = classRegex.exec(content)) !== null) {
|
|
118
|
+
const className = match[1];
|
|
119
|
+
const componentName = extractComponentName(className);
|
|
120
|
+
const classNode = nodes.find(
|
|
121
|
+
(n) => n.kind === "class" && n.name === className
|
|
122
|
+
);
|
|
123
|
+
if (classNode && componentName) {
|
|
124
|
+
managers.push({ componentName, nodeId: classNode.id, filePath: f, className });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (f.endsWith(".java") || f.endsWith(".kt")) {
|
|
129
|
+
const classRegex = /class\s+(\w+(?:Manager|ViewManager))\s+(?:extends|:)\s+\w*(?:ViewManager|SimpleViewManager|ViewGroupManager)/g;
|
|
130
|
+
let match;
|
|
131
|
+
while ((match = classRegex.exec(content)) !== null) {
|
|
132
|
+
const className = match[1];
|
|
133
|
+
const componentName = extractComponentName(className);
|
|
134
|
+
const classNode = nodes.find(
|
|
135
|
+
(n) => n.kind === "class" && n.name === className
|
|
136
|
+
);
|
|
137
|
+
if (classNode && componentName) {
|
|
138
|
+
managers.push({ componentName, nodeId: classNode.id, filePath: f, className });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const getNameMatch = content.match(/getName\s*\(\s*\)\s*(?::\s*String\s*)?\{[^}]*return\s*"(\w+)"/);
|
|
142
|
+
if (getNameMatch) {
|
|
143
|
+
const registeredName = getNameMatch[1];
|
|
144
|
+
const classMatch = content.match(/class\s+(\w+)/);
|
|
145
|
+
if (classMatch) {
|
|
146
|
+
const classNode = nodes.find((n) => n.kind === "class" && n.name === classMatch[1]);
|
|
147
|
+
if (classNode) {
|
|
148
|
+
const exists = managers.some((m) => m.nodeId === classNode.id);
|
|
149
|
+
if (!exists) {
|
|
150
|
+
managers.push({
|
|
151
|
+
componentName: registeredName,
|
|
152
|
+
nodeId: classNode.id,
|
|
153
|
+
filePath: f,
|
|
154
|
+
className: classMatch[1]
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return managers;
|
|
163
|
+
}
|
|
164
|
+
function extractComponentName(className) {
|
|
165
|
+
let name = className;
|
|
166
|
+
for (const prefix of VIEW_MANAGER_PREFIXES) {
|
|
167
|
+
if (prefix && name.startsWith(prefix)) {
|
|
168
|
+
name = name.slice(prefix.length);
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
for (const suffix of VIEW_MANAGER_SUFFIXES) {
|
|
173
|
+
if (name.endsWith(suffix)) {
|
|
174
|
+
name = name.slice(0, -suffix.length);
|
|
175
|
+
if (name.length > 0) return name;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return name.length > 0 ? name : null;
|
|
179
|
+
}
|
|
180
|
+
const nativeViewsBridge = {
|
|
181
|
+
name: "native-views-bridge",
|
|
182
|
+
detect(context) {
|
|
183
|
+
const files = context.getAllFiles();
|
|
184
|
+
for (const f of files) {
|
|
185
|
+
const fileName = f.split("/").pop() ?? "";
|
|
186
|
+
if (fileName.includes("ViewManager") || fileName.includes("ComponentView")) {
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
if (f.endsWith(".tsx") || f.endsWith(".jsx") || f.endsWith(".ts") || f.endsWith(".js")) {
|
|
190
|
+
const content = context.readFile(f);
|
|
191
|
+
if (content && (content.includes("requireNativeComponent") || content.includes("codegenNativeComponent"))) {
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
},
|
|
198
|
+
resolve(context) {
|
|
199
|
+
const edges = [];
|
|
200
|
+
const usages = findNativeViewUsages(context);
|
|
201
|
+
const managers = findNativeViewManagers(context);
|
|
202
|
+
for (const usage of usages) {
|
|
203
|
+
for (const manager of managers) {
|
|
204
|
+
if (usage.componentName === manager.componentName) {
|
|
205
|
+
edges.push({
|
|
206
|
+
source: usage.usageNodeId,
|
|
207
|
+
target: manager.nodeId,
|
|
208
|
+
kind: "references",
|
|
209
|
+
confidence: "inferred",
|
|
210
|
+
confidenceScore: 0.85,
|
|
211
|
+
metadata: {
|
|
212
|
+
synthesizedBy: "native-views-bridge",
|
|
213
|
+
provenance: "heuristic",
|
|
214
|
+
componentName: usage.componentName,
|
|
215
|
+
nativeClass: manager.className
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (usage.componentName.toLowerCase() === manager.componentName.toLowerCase() && usage.componentName !== manager.componentName) {
|
|
220
|
+
edges.push({
|
|
221
|
+
source: usage.usageNodeId,
|
|
222
|
+
target: manager.nodeId,
|
|
223
|
+
kind: "references",
|
|
224
|
+
confidence: "inferred",
|
|
225
|
+
confidenceScore: 0.75,
|
|
226
|
+
metadata: {
|
|
227
|
+
synthesizedBy: "native-views-bridge",
|
|
228
|
+
provenance: "heuristic",
|
|
229
|
+
componentName: usage.componentName,
|
|
230
|
+
nativeClass: manager.className,
|
|
231
|
+
matchType: "case-insensitive"
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return edges;
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
241
|
+
0 && (module.exports = {
|
|
242
|
+
nativeViewsBridge
|
|
243
|
+
});
|
|
244
|
+
//# sourceMappingURL=native-views.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/resolution/bridges/native-views.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Fabric/Paper Native Views Bridge\n *\n * Synthesizes edges between JSX usage of native components (<MyView />)\n * and their native view manager implementations. Uses convention-based\n * name + suffix lookup to match components to their native counterparts.\n *\n * Conventions:\n * <MyView /> \u2192 MyViewManager, MyViewComponentView, RCTMyViewManager\n */\n\nimport type { Node } from '../../types';\nimport type { ResolutionContext } from '../../frameworks/types';\nimport type { BridgeResolver, SynthesizedEdge } from './index';\n\n// \u2500\u2500 Helpers \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\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface NativeViewUsage {\n componentName: string;\n usageNodeId: string;\n filePath: string;\n}\n\ninterface NativeViewManager {\n componentName: string; // The base component name (without Manager suffix)\n nodeId: string;\n filePath: string;\n className: string;\n}\n\n/**\n * Common suffixes for native view manager classes.\n */\nconst VIEW_MANAGER_SUFFIXES = [\n 'Manager',\n 'ViewManager',\n 'ComponentView',\n 'NativeComponent',\n];\n\n/**\n * Common prefixes for native view manager classes.\n */\nconst VIEW_MANAGER_PREFIXES = ['RCT', ''];\n\n/**\n * Find JSX usages of native components in JS/TS files.\n * Native components are typically PascalCase and imported from native modules.\n */\nfunction findNativeViewUsages(context: ResolutionContext): NativeViewUsage[] {\n const usages: NativeViewUsage[] = [];\n const files = context.getAllFiles();\n\n for (const f of files) {\n if (!f.endsWith('.tsx') && !f.endsWith('.jsx')) continue;\n\n const content = context.readFile(f);\n if (!content) continue;\n\n const nodes = context.getNodesInFile(f);\n\n // Look for requireNativeComponent('ComponentName') patterns\n const requireNativeRegex = /requireNativeComponent\\s*(?:<[^>]*>)?\\s*\\(\\s*['\"](\\w+)['\"]\\s*\\)/g;\n let match: RegExpExecArray | null;\n\n while ((match = requireNativeRegex.exec(content)) !== null) {\n const componentName = match[1];\n const lineNum = content.slice(0, match.index).split('\\n').length;\n\n // Find enclosing node or file-level node\n const enclosing = nodes.find(\n n => n.startLine <= lineNum && n.endLine >= lineNum\n );\n\n if (enclosing) {\n usages.push({ componentName, usageNodeId: enclosing.id, filePath: f });\n }\n }\n\n // Look for codegenNativeComponent('ComponentName') patterns (Fabric)\n const codegenRegex = /codegenNativeComponent\\s*(?:<[^>]*>)?\\s*\\(\\s*['\"](\\w+)['\"]\\s*\\)/g;\n while ((match = codegenRegex.exec(content)) !== null) {\n const componentName = match[1];\n const lineNum = content.slice(0, match.index).split('\\n').length;\n\n const enclosing = nodes.find(\n n => n.startLine <= lineNum && n.endLine >= lineNum\n );\n\n if (enclosing) {\n usages.push({ componentName, usageNodeId: enclosing.id, filePath: f });\n }\n }\n\n // Look for UIManager.getViewManagerConfig('ComponentName')\n const uiManagerRegex = /UIManager\\.getViewManagerConfig\\s*\\(\\s*['\"](\\w+)['\"]\\s*\\)/g;\n while ((match = uiManagerRegex.exec(content)) !== null) {\n const componentName = match[1];\n const lineNum = content.slice(0, match.index).split('\\n').length;\n\n const enclosing = nodes.find(\n n => n.startLine <= lineNum && n.endLine >= lineNum\n );\n\n if (enclosing) {\n usages.push({ componentName, usageNodeId: enclosing.id, filePath: f });\n }\n }\n }\n\n return usages;\n}\n\n/**\n * Find native view manager classes in ObjC/Swift/Java/Kotlin files.\n */\nfunction findNativeViewManagers(context: ResolutionContext): NativeViewManager[] {\n const managers: NativeViewManager[] = [];\n const files = context.getAllFiles();\n\n for (const f of files) {\n if (!f.endsWith('.m') && !f.endsWith('.mm') && !f.endsWith('.swift') &&\n !f.endsWith('.java') && !f.endsWith('.kt') && !f.endsWith('.h')) {\n continue;\n }\n\n const content = context.readFile(f);\n if (!content) continue;\n\n const nodes = context.getNodesInFile(f);\n\n // ObjC: @implementation RCTMyViewManager or subclass of RCTViewManager\n if (f.endsWith('.m') || f.endsWith('.mm') || f.endsWith('.h')) {\n // Find class implementations/declarations\n const implRegex = /@(?:implementation|interface)\\s+(\\w+(?:Manager|ViewManager|ComponentView))\\b/g;\n let match: RegExpExecArray | null;\n\n while ((match = implRegex.exec(content)) !== null) {\n const className = match[1];\n const componentName = extractComponentName(className);\n\n const classNode = nodes.find(\n n => n.kind === 'class' && n.name === className\n );\n\n if (classNode && componentName) {\n managers.push({ componentName, nodeId: classNode.id, filePath: f, className });\n }\n }\n\n // Also check RCT_EXPORT_VIEW_PROPERTY patterns\n if (content.includes('RCT_EXPORT_VIEW_PROPERTY') || content.includes('RCTViewManager')) {\n const classImpl = content.match(/@implementation\\s+(\\w+)/);\n if (classImpl) {\n const className = classImpl[1];\n const componentName = extractComponentName(className);\n const classNode = nodes.find(n => n.kind === 'class' && n.name === className);\n\n if (classNode && componentName) {\n const exists = managers.some(m => m.nodeId === classNode.id);\n if (!exists) {\n managers.push({ componentName, nodeId: classNode.id, filePath: f, className });\n }\n }\n }\n }\n }\n\n // Swift: class that extends RCTViewManager or uses @objc\n if (f.endsWith('.swift')) {\n const classRegex = /class\\s+(\\w+(?:Manager|ViewManager|ComponentView))\\s*:\\s*(\\w+)/g;\n let match: RegExpExecArray | null;\n\n while ((match = classRegex.exec(content)) !== null) {\n const className = match[1];\n const componentName = extractComponentName(className);\n\n const classNode = nodes.find(\n n => n.kind === 'class' && n.name === className\n );\n\n if (classNode && componentName) {\n managers.push({ componentName, nodeId: classNode.id, filePath: f, className });\n }\n }\n }\n\n // Java/Kotlin: class extending SimpleViewManager or ViewGroupManager\n if (f.endsWith('.java') || f.endsWith('.kt')) {\n const classRegex = /class\\s+(\\w+(?:Manager|ViewManager))\\s+(?:extends|:)\\s+\\w*(?:ViewManager|SimpleViewManager|ViewGroupManager)/g;\n let match: RegExpExecArray | null;\n\n while ((match = classRegex.exec(content)) !== null) {\n const className = match[1];\n const componentName = extractComponentName(className);\n\n const classNode = nodes.find(\n n => n.kind === 'class' && n.name === className\n );\n\n if (classNode && componentName) {\n managers.push({ componentName, nodeId: classNode.id, filePath: f, className });\n }\n }\n\n // Also check getName() return value for the component name\n const getNameMatch = content.match(/getName\\s*\\(\\s*\\)\\s*(?::\\s*String\\s*)?\\{[^}]*return\\s*\"(\\w+)\"/);\n if (getNameMatch) {\n const registeredName = getNameMatch[1];\n const classMatch = content.match(/class\\s+(\\w+)/);\n if (classMatch) {\n const classNode = nodes.find(n => n.kind === 'class' && n.name === classMatch[1]);\n if (classNode) {\n const exists = managers.some(m => m.nodeId === classNode.id);\n if (!exists) {\n managers.push({\n componentName: registeredName,\n nodeId: classNode.id,\n filePath: f,\n className: classMatch[1],\n });\n }\n }\n }\n }\n }\n }\n\n return managers;\n}\n\n/**\n * Extract the base component name from a view manager class name.\n * RCTMyViewManager \u2192 MyView\n * MyViewManager \u2192 MyView\n * MyComponentView \u2192 My\n */\nfunction extractComponentName(className: string): string | null {\n // Strip prefixes\n let name = className;\n for (const prefix of VIEW_MANAGER_PREFIXES) {\n if (prefix && name.startsWith(prefix)) {\n name = name.slice(prefix.length);\n break;\n }\n }\n\n // Strip suffixes\n for (const suffix of VIEW_MANAGER_SUFFIXES) {\n if (name.endsWith(suffix)) {\n name = name.slice(0, -suffix.length);\n if (name.length > 0) return name;\n }\n }\n\n return name.length > 0 ? name : null;\n}\n\n// \u2500\u2500 Bridge Implementation \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\nexport const nativeViewsBridge: BridgeResolver = {\n name: 'native-views-bridge',\n\n detect(context: ResolutionContext): boolean {\n const files = context.getAllFiles();\n\n // Check for view manager files or codegen specs\n for (const f of files) {\n const fileName = f.split('/').pop() ?? '';\n\n // Check for ViewManager pattern in filenames\n if (fileName.includes('ViewManager') || fileName.includes('ComponentView')) {\n return true;\n }\n\n // Check for requireNativeComponent or codegenNativeComponent in JS/TS\n if (f.endsWith('.tsx') || f.endsWith('.jsx') || f.endsWith('.ts') || f.endsWith('.js')) {\n const content = context.readFile(f);\n if (content && (\n content.includes('requireNativeComponent') ||\n content.includes('codegenNativeComponent')\n )) {\n return true;\n }\n }\n }\n\n return false;\n },\n\n resolve(context: ResolutionContext): SynthesizedEdge[] {\n const edges: SynthesizedEdge[] = [];\n\n const usages = findNativeViewUsages(context);\n const managers = findNativeViewManagers(context);\n\n // Match usages to managers by component name\n for (const usage of usages) {\n for (const manager of managers) {\n // Direct name match\n if (usage.componentName === manager.componentName) {\n edges.push({\n source: usage.usageNodeId,\n target: manager.nodeId,\n kind: 'references',\n confidence: 'inferred',\n confidenceScore: 0.85,\n metadata: {\n synthesizedBy: 'native-views-bridge',\n provenance: 'heuristic',\n componentName: usage.componentName,\n nativeClass: manager.className,\n },\n });\n }\n\n // Also try case-insensitive match\n if (usage.componentName.toLowerCase() === manager.componentName.toLowerCase() &&\n usage.componentName !== manager.componentName) {\n edges.push({\n source: usage.usageNodeId,\n target: manager.nodeId,\n kind: 'references',\n confidence: 'inferred',\n confidenceScore: 0.75,\n metadata: {\n synthesizedBy: 'native-views-bridge',\n provenance: 'heuristic',\n componentName: usage.componentName,\n nativeClass: manager.className,\n matchType: 'case-insensitive',\n },\n });\n }\n }\n }\n\n return edges;\n },\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|