@grafema/core 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +76 -0
- package/dist/Orchestrator.d.ts +142 -0
- package/dist/Orchestrator.d.ts.map +1 -0
- package/dist/Orchestrator.js +481 -0
- package/dist/api/GraphAPI.d.ts +87 -0
- package/dist/api/GraphAPI.d.ts.map +1 -0
- package/dist/api/GraphAPI.js +210 -0
- package/dist/api/GuaranteeAPI.d.ts +147 -0
- package/dist/api/GuaranteeAPI.d.ts.map +1 -0
- package/dist/api/GuaranteeAPI.js +288 -0
- package/dist/core/ASTWorker.d.ts +133 -0
- package/dist/core/ASTWorker.d.ts.map +1 -0
- package/dist/core/ASTWorker.js +352 -0
- package/dist/core/ASTWorkerPool.d.ts +85 -0
- package/dist/core/ASTWorkerPool.d.ts.map +1 -0
- package/dist/core/ASTWorkerPool.js +207 -0
- package/dist/core/AnalysisQueue.d.ts +104 -0
- package/dist/core/AnalysisQueue.d.ts.map +1 -0
- package/dist/core/AnalysisQueue.js +299 -0
- package/dist/core/AnalysisWorker.d.ts +14 -0
- package/dist/core/AnalysisWorker.d.ts.map +1 -0
- package/dist/core/AnalysisWorker.js +307 -0
- package/dist/core/GraphBackend.d.ts +156 -0
- package/dist/core/GraphBackend.d.ts.map +1 -0
- package/dist/core/GraphBackend.js +85 -0
- package/dist/core/GuaranteeManager.d.ts +230 -0
- package/dist/core/GuaranteeManager.d.ts.map +1 -0
- package/dist/core/GuaranteeManager.js +352 -0
- package/dist/core/ManifestStore.d.ts +71 -0
- package/dist/core/ManifestStore.d.ts.map +1 -0
- package/dist/core/ManifestStore.js +146 -0
- package/dist/core/NodeFactory.d.ts +160 -0
- package/dist/core/NodeFactory.d.ts.map +1 -0
- package/dist/core/NodeFactory.js +137 -0
- package/dist/core/NodeId.d.ts +88 -0
- package/dist/core/NodeId.d.ts.map +1 -0
- package/dist/core/NodeId.js +170 -0
- package/dist/core/ParallelAnalyzer.d.ts +120 -0
- package/dist/core/ParallelAnalyzer.d.ts.map +1 -0
- package/dist/core/ParallelAnalyzer.js +331 -0
- package/dist/core/PriorityQueue.d.ts +106 -0
- package/dist/core/PriorityQueue.d.ts.map +1 -0
- package/dist/core/PriorityQueue.js +168 -0
- package/dist/core/Profiler.d.ts +75 -0
- package/dist/core/Profiler.d.ts.map +1 -0
- package/dist/core/Profiler.js +149 -0
- package/dist/core/QueueWorker.d.ts +12 -0
- package/dist/core/QueueWorker.d.ts.map +1 -0
- package/dist/core/QueueWorker.js +567 -0
- package/dist/core/RFDBClient.d.ts +179 -0
- package/dist/core/RFDBClient.d.ts.map +1 -0
- package/dist/core/RFDBClient.js +429 -0
- package/dist/core/Task.d.ts +56 -0
- package/dist/core/Task.d.ts.map +1 -0
- package/dist/core/Task.js +85 -0
- package/dist/core/TaskTypes.d.ts +20 -0
- package/dist/core/TaskTypes.d.ts.map +1 -0
- package/dist/core/TaskTypes.js +10 -0
- package/dist/core/VersionManager.d.ts +166 -0
- package/dist/core/VersionManager.d.ts.map +1 -0
- package/dist/core/VersionManager.js +237 -0
- package/dist/core/WorkerPool.d.ts +82 -0
- package/dist/core/WorkerPool.d.ts.map +1 -0
- package/dist/core/WorkerPool.js +109 -0
- package/dist/core/nodes/CallSiteNode.d.ts +26 -0
- package/dist/core/nodes/CallSiteNode.d.ts.map +1 -0
- package/dist/core/nodes/CallSiteNode.js +44 -0
- package/dist/core/nodes/ClassNode.d.ts +25 -0
- package/dist/core/nodes/ClassNode.d.ts.map +1 -0
- package/dist/core/nodes/ClassNode.js +40 -0
- package/dist/core/nodes/ConstantNode.d.ts +24 -0
- package/dist/core/nodes/ConstantNode.d.ts.map +1 -0
- package/dist/core/nodes/ConstantNode.js +39 -0
- package/dist/core/nodes/DatabaseQueryNode.d.ts +22 -0
- package/dist/core/nodes/DatabaseQueryNode.d.ts.map +1 -0
- package/dist/core/nodes/DatabaseQueryNode.js +37 -0
- package/dist/core/nodes/EntrypointNode.d.ts +102 -0
- package/dist/core/nodes/EntrypointNode.d.ts.map +1 -0
- package/dist/core/nodes/EntrypointNode.js +119 -0
- package/dist/core/nodes/EventListenerNode.d.ts +25 -0
- package/dist/core/nodes/EventListenerNode.d.ts.map +1 -0
- package/dist/core/nodes/EventListenerNode.js +39 -0
- package/dist/core/nodes/ExportNode.d.ts +26 -0
- package/dist/core/nodes/ExportNode.d.ts.map +1 -0
- package/dist/core/nodes/ExportNode.js +40 -0
- package/dist/core/nodes/ExternalStdioNode.d.ts +17 -0
- package/dist/core/nodes/ExternalStdioNode.d.ts.map +1 -0
- package/dist/core/nodes/ExternalStdioNode.js +26 -0
- package/dist/core/nodes/FunctionNode.d.ts +27 -0
- package/dist/core/nodes/FunctionNode.d.ts.map +1 -0
- package/dist/core/nodes/FunctionNode.js +53 -0
- package/dist/core/nodes/GuaranteeNode.d.ts +76 -0
- package/dist/core/nodes/GuaranteeNode.d.ts.map +1 -0
- package/dist/core/nodes/GuaranteeNode.js +117 -0
- package/dist/core/nodes/HttpRequestNode.d.ts +24 -0
- package/dist/core/nodes/HttpRequestNode.d.ts.map +1 -0
- package/dist/core/nodes/HttpRequestNode.js +38 -0
- package/dist/core/nodes/ImportNode.d.ts +27 -0
- package/dist/core/nodes/ImportNode.d.ts.map +1 -0
- package/dist/core/nodes/ImportNode.js +43 -0
- package/dist/core/nodes/LiteralNode.d.ts +26 -0
- package/dist/core/nodes/LiteralNode.d.ts.map +1 -0
- package/dist/core/nodes/LiteralNode.js +40 -0
- package/dist/core/nodes/MethodCallNode.d.ts +29 -0
- package/dist/core/nodes/MethodCallNode.d.ts.map +1 -0
- package/dist/core/nodes/MethodCallNode.js +47 -0
- package/dist/core/nodes/MethodNode.d.ts +29 -0
- package/dist/core/nodes/MethodNode.d.ts.map +1 -0
- package/dist/core/nodes/MethodNode.js +44 -0
- package/dist/core/nodes/ModuleNode.d.ts +29 -0
- package/dist/core/nodes/ModuleNode.d.ts.map +1 -0
- package/dist/core/nodes/ModuleNode.js +49 -0
- package/dist/core/nodes/NodeKind.d.ts +91 -0
- package/dist/core/nodes/NodeKind.d.ts.map +1 -0
- package/dist/core/nodes/NodeKind.js +146 -0
- package/dist/core/nodes/ParameterNode.d.ts +26 -0
- package/dist/core/nodes/ParameterNode.d.ts.map +1 -0
- package/dist/core/nodes/ParameterNode.js +43 -0
- package/dist/core/nodes/ScopeNode.d.ts +32 -0
- package/dist/core/nodes/ScopeNode.d.ts.map +1 -0
- package/dist/core/nodes/ScopeNode.js +47 -0
- package/dist/core/nodes/ServiceNode.d.ts +44 -0
- package/dist/core/nodes/ServiceNode.d.ts.map +1 -0
- package/dist/core/nodes/ServiceNode.js +49 -0
- package/dist/core/nodes/VariableDeclarationNode.d.ts +22 -0
- package/dist/core/nodes/VariableDeclarationNode.d.ts.map +1 -0
- package/dist/core/nodes/VariableDeclarationNode.js +38 -0
- package/dist/core/nodes/index.d.ts +25 -0
- package/dist/core/nodes/index.d.ts.map +1 -0
- package/dist/core/nodes/index.js +30 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/plugins/Plugin.d.ts +44 -0
- package/dist/plugins/Plugin.d.ts.map +1 -0
- package/dist/plugins/Plugin.js +46 -0
- package/dist/plugins/analysis/DatabaseAnalyzer.d.ts +23 -0
- package/dist/plugins/analysis/DatabaseAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/DatabaseAnalyzer.js +260 -0
- package/dist/plugins/analysis/ExpressAnalyzer.d.ts +19 -0
- package/dist/plugins/analysis/ExpressAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/ExpressAnalyzer.js +306 -0
- package/dist/plugins/analysis/ExpressRouteAnalyzer.d.ts +17 -0
- package/dist/plugins/analysis/ExpressRouteAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/ExpressRouteAnalyzer.js +308 -0
- package/dist/plugins/analysis/FetchAnalyzer.d.ts +38 -0
- package/dist/plugins/analysis/FetchAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/FetchAnalyzer.js +344 -0
- package/dist/plugins/analysis/IncrementalAnalysisPlugin.d.ts +65 -0
- package/dist/plugins/analysis/IncrementalAnalysisPlugin.d.ts.map +1 -0
- package/dist/plugins/analysis/IncrementalAnalysisPlugin.js +472 -0
- package/dist/plugins/analysis/JSASTAnalyzer.d.ts +84 -0
- package/dist/plugins/analysis/JSASTAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/JSASTAnalyzer.js +1378 -0
- package/dist/plugins/analysis/ReactAnalyzer.d.ts +90 -0
- package/dist/plugins/analysis/ReactAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/ReactAnalyzer.js +1153 -0
- package/dist/plugins/analysis/RustAnalyzer.d.ts +13 -0
- package/dist/plugins/analysis/RustAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/RustAnalyzer.js +259 -0
- package/dist/plugins/analysis/SQLiteAnalyzer.d.ts +21 -0
- package/dist/plugins/analysis/SQLiteAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/SQLiteAnalyzer.js +317 -0
- package/dist/plugins/analysis/ServiceLayerAnalyzer.d.ts +35 -0
- package/dist/plugins/analysis/ServiceLayerAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/ServiceLayerAnalyzer.js +303 -0
- package/dist/plugins/analysis/SocketIOAnalyzer.d.ts +33 -0
- package/dist/plugins/analysis/SocketIOAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/SocketIOAnalyzer.js +283 -0
- package/dist/plugins/analysis/SystemDbAnalyzer.d.ts +27 -0
- package/dist/plugins/analysis/SystemDbAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/SystemDbAnalyzer.js +211 -0
- package/dist/plugins/analysis/ast/ConditionParser.d.ts +85 -0
- package/dist/plugins/analysis/ast/ConditionParser.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/ConditionParser.js +277 -0
- package/dist/plugins/analysis/ast/ExpressionEvaluator.d.ts +15 -0
- package/dist/plugins/analysis/ast/ExpressionEvaluator.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/ExpressionEvaluator.js +91 -0
- package/dist/plugins/analysis/ast/GraphBuilder.d.ts +77 -0
- package/dist/plugins/analysis/ast/GraphBuilder.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/GraphBuilder.js +1077 -0
- package/dist/plugins/analysis/ast/OxcAdapter.d.ts +41 -0
- package/dist/plugins/analysis/ast/OxcAdapter.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/OxcAdapter.js +40 -0
- package/dist/plugins/analysis/ast/types.d.ts +346 -0
- package/dist/plugins/analysis/ast/types.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/types.js +4 -0
- package/dist/plugins/analysis/ast/visitors/ASTVisitor.d.ts +93 -0
- package/dist/plugins/analysis/ast/visitors/ASTVisitor.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/visitors/ASTVisitor.js +24 -0
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.d.ts +77 -0
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.js +377 -0
- package/dist/plugins/analysis/ast/visitors/ClassVisitor.d.ts +27 -0
- package/dist/plugins/analysis/ast/visitors/ClassVisitor.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/visitors/ClassVisitor.js +232 -0
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.d.ts +25 -0
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.js +172 -0
- package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.d.ts +29 -0
- package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.js +180 -0
- package/dist/plugins/analysis/ast/visitors/TypeScriptVisitor.d.ts +14 -0
- package/dist/plugins/analysis/ast/visitors/TypeScriptVisitor.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/visitors/TypeScriptVisitor.js +200 -0
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.d.ts +45 -0
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.js +150 -0
- package/dist/plugins/analysis/ast/visitors/index.d.ts +17 -0
- package/dist/plugins/analysis/ast/visitors/index.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/visitors/index.js +13 -0
- package/dist/plugins/discovery/DiscoveryPlugin.d.ts +34 -0
- package/dist/plugins/discovery/DiscoveryPlugin.d.ts.map +1 -0
- package/dist/plugins/discovery/DiscoveryPlugin.js +26 -0
- package/dist/plugins/discovery/MonorepoServiceDiscovery.d.ts +26 -0
- package/dist/plugins/discovery/MonorepoServiceDiscovery.d.ts.map +1 -0
- package/dist/plugins/discovery/MonorepoServiceDiscovery.js +79 -0
- package/dist/plugins/discovery/SimpleProjectDiscovery.d.ts +14 -0
- package/dist/plugins/discovery/SimpleProjectDiscovery.d.ts.map +1 -0
- package/dist/plugins/discovery/SimpleProjectDiscovery.js +65 -0
- package/dist/plugins/discovery/ZonServiceDiscovery.d.ts +19 -0
- package/dist/plugins/discovery/ZonServiceDiscovery.d.ts.map +1 -0
- package/dist/plugins/discovery/ZonServiceDiscovery.js +204 -0
- package/dist/plugins/enrichment/AliasTracker.d.ts +40 -0
- package/dist/plugins/enrichment/AliasTracker.d.ts.map +1 -0
- package/dist/plugins/enrichment/AliasTracker.js +290 -0
- package/dist/plugins/enrichment/HTTPConnectionEnricher.d.ts +30 -0
- package/dist/plugins/enrichment/HTTPConnectionEnricher.d.ts.map +1 -0
- package/dist/plugins/enrichment/HTTPConnectionEnricher.js +135 -0
- package/dist/plugins/enrichment/ImportExportLinker.d.ts +30 -0
- package/dist/plugins/enrichment/ImportExportLinker.d.ts.map +1 -0
- package/dist/plugins/enrichment/ImportExportLinker.js +176 -0
- package/dist/plugins/enrichment/InstanceOfResolver.d.ts +21 -0
- package/dist/plugins/enrichment/InstanceOfResolver.d.ts.map +1 -0
- package/dist/plugins/enrichment/InstanceOfResolver.js +117 -0
- package/dist/plugins/enrichment/MethodCallResolver.d.ts +41 -0
- package/dist/plugins/enrichment/MethodCallResolver.d.ts.map +1 -0
- package/dist/plugins/enrichment/MethodCallResolver.js +252 -0
- package/dist/plugins/enrichment/MountPointResolver.d.ts +26 -0
- package/dist/plugins/enrichment/MountPointResolver.d.ts.map +1 -0
- package/dist/plugins/enrichment/MountPointResolver.js +189 -0
- package/dist/plugins/enrichment/PrefixEvaluator.d.ts +89 -0
- package/dist/plugins/enrichment/PrefixEvaluator.d.ts.map +1 -0
- package/dist/plugins/enrichment/PrefixEvaluator.js +415 -0
- package/dist/plugins/enrichment/RustFFIEnricher.d.ts +25 -0
- package/dist/plugins/enrichment/RustFFIEnricher.d.ts.map +1 -0
- package/dist/plugins/enrichment/RustFFIEnricher.js +170 -0
- package/dist/plugins/enrichment/ValueDomainAnalyzer.d.ts +114 -0
- package/dist/plugins/enrichment/ValueDomainAnalyzer.d.ts.map +1 -0
- package/dist/plugins/enrichment/ValueDomainAnalyzer.js +464 -0
- package/dist/plugins/indexing/IncrementalModuleIndexer.d.ts +27 -0
- package/dist/plugins/indexing/IncrementalModuleIndexer.d.ts.map +1 -0
- package/dist/plugins/indexing/IncrementalModuleIndexer.js +238 -0
- package/dist/plugins/indexing/JSModuleIndexer.d.ts +33 -0
- package/dist/plugins/indexing/JSModuleIndexer.d.ts.map +1 -0
- package/dist/plugins/indexing/JSModuleIndexer.js +299 -0
- package/dist/plugins/indexing/RustModuleIndexer.d.ts +28 -0
- package/dist/plugins/indexing/RustModuleIndexer.d.ts.map +1 -0
- package/dist/plugins/indexing/RustModuleIndexer.js +140 -0
- package/dist/plugins/indexing/ServiceDetector.d.ts +46 -0
- package/dist/plugins/indexing/ServiceDetector.d.ts.map +1 -0
- package/dist/plugins/indexing/ServiceDetector.js +164 -0
- package/dist/plugins/validation/CallResolverValidator.d.ts +23 -0
- package/dist/plugins/validation/CallResolverValidator.d.ts.map +1 -0
- package/dist/plugins/validation/CallResolverValidator.js +108 -0
- package/dist/plugins/validation/DataFlowValidator.d.ts +24 -0
- package/dist/plugins/validation/DataFlowValidator.d.ts.map +1 -0
- package/dist/plugins/validation/DataFlowValidator.js +148 -0
- package/dist/plugins/validation/EvalBanValidator.d.ts +25 -0
- package/dist/plugins/validation/EvalBanValidator.d.ts.map +1 -0
- package/dist/plugins/validation/EvalBanValidator.js +123 -0
- package/dist/plugins/validation/GraphConnectivityValidator.d.ts +11 -0
- package/dist/plugins/validation/GraphConnectivityValidator.d.ts.map +1 -0
- package/dist/plugins/validation/GraphConnectivityValidator.js +135 -0
- package/dist/plugins/validation/SQLInjectionValidator.d.ts +43 -0
- package/dist/plugins/validation/SQLInjectionValidator.d.ts.map +1 -0
- package/dist/plugins/validation/SQLInjectionValidator.js +251 -0
- package/dist/plugins/validation/ShadowingDetector.d.ts +26 -0
- package/dist/plugins/validation/ShadowingDetector.d.ts.map +1 -0
- package/dist/plugins/validation/ShadowingDetector.js +119 -0
- package/dist/plugins/validation/TypeScriptDeadCodeValidator.d.ts +21 -0
- package/dist/plugins/validation/TypeScriptDeadCodeValidator.d.ts.map +1 -0
- package/dist/plugins/validation/TypeScriptDeadCodeValidator.js +151 -0
- package/dist/plugins/vcs/GitPlugin.d.ts +84 -0
- package/dist/plugins/vcs/GitPlugin.d.ts.map +1 -0
- package/dist/plugins/vcs/GitPlugin.js +295 -0
- package/dist/plugins/vcs/VCSPlugin.d.ts +133 -0
- package/dist/plugins/vcs/VCSPlugin.d.ts.map +1 -0
- package/dist/plugins/vcs/VCSPlugin.js +82 -0
- package/dist/plugins/vcs/index.d.ts +10 -0
- package/dist/plugins/vcs/index.d.ts.map +1 -0
- package/dist/plugins/vcs/index.js +18 -0
- package/dist/storage/backends/RFDBServerBackend.d.ts +258 -0
- package/dist/storage/backends/RFDBServerBackend.d.ts.map +1 -0
- package/dist/storage/backends/RFDBServerBackend.js +565 -0
- package/dist/storage/backends/typeValidation.d.ts +47 -0
- package/dist/storage/backends/typeValidation.d.ts.map +1 -0
- package/dist/storage/backends/typeValidation.js +137 -0
- package/dist/validation/PathValidator.d.ts +81 -0
- package/dist/validation/PathValidator.d.ts.map +1 -0
- package/dist/validation/PathValidator.js +251 -0
- package/package.json +57 -0
- package/src/.rfguard/current-session.txt +1 -0
- package/src/Orchestrator.ts +673 -0
- package/src/api/GraphAPI.ts +305 -0
- package/src/api/GuaranteeAPI.ts +401 -0
- package/src/core/ASTWorker.ts +567 -0
- package/src/core/ASTWorkerPool.ts +299 -0
- package/src/core/AnalysisQueue.ts +447 -0
- package/src/core/AnalysisWorker.ts +410 -0
- package/src/core/GraphBackend.ts +265 -0
- package/src/core/GuaranteeManager.ts +581 -0
- package/src/core/ManifestStore.ts +196 -0
- package/src/core/NodeFactory.ts +274 -0
- package/src/core/NodeId.ts +257 -0
- package/src/core/ParallelAnalyzer.ts +476 -0
- package/src/core/PriorityQueue.ts +227 -0
- package/src/core/Profiler.ts +188 -0
- package/src/core/QueueWorker.ts +780 -0
- package/src/core/Task.ts +107 -0
- package/src/core/TaskTypes.ts +40 -0
- package/src/core/VersionManager.ts +404 -0
- package/src/core/WorkerPool.ts +180 -0
- package/src/core/nodes/CallSiteNode.ts +72 -0
- package/src/core/nodes/ClassNode.ts +69 -0
- package/src/core/nodes/ConstantNode.ts +63 -0
- package/src/core/nodes/DatabaseQueryNode.ts +60 -0
- package/src/core/nodes/EntrypointNode.ts +164 -0
- package/src/core/nodes/EventListenerNode.ts +64 -0
- package/src/core/nodes/ExportNode.ts +71 -0
- package/src/core/nodes/ExternalStdioNode.ts +36 -0
- package/src/core/nodes/FunctionNode.ts +78 -0
- package/src/core/nodes/GuaranteeNode.ts +162 -0
- package/src/core/nodes/HttpRequestNode.ts +63 -0
- package/src/core/nodes/ImportNode.ts +75 -0
- package/src/core/nodes/LiteralNode.ts +67 -0
- package/src/core/nodes/MethodCallNode.ts +79 -0
- package/src/core/nodes/MethodNode.ts +78 -0
- package/src/core/nodes/ModuleNode.ts +74 -0
- package/src/core/nodes/NodeKind.ts +171 -0
- package/src/core/nodes/ParameterNode.ts +73 -0
- package/src/core/nodes/ScopeNode.ts +80 -0
- package/src/core/nodes/ServiceNode.ts +86 -0
- package/src/core/nodes/VariableDeclarationNode.ts +60 -0
- package/src/core/nodes/index.ts +49 -0
- package/src/index.ts +93 -0
- package/src/plugins/Plugin.ts +74 -0
- package/src/plugins/analysis/DatabaseAnalyzer.ts +322 -0
- package/src/plugins/analysis/ExpressAnalyzer.ts +401 -0
- package/src/plugins/analysis/ExpressRouteAnalyzer.ts +414 -0
- package/src/plugins/analysis/FetchAnalyzer.ts +441 -0
- package/src/plugins/analysis/IncrementalAnalysisPlugin.ts +686 -0
- package/src/plugins/analysis/JSASTAnalyzer.ts +1680 -0
- package/src/plugins/analysis/ReactAnalyzer.ts +1368 -0
- package/src/plugins/analysis/RustAnalyzer.ts +438 -0
- package/src/plugins/analysis/SQLiteAnalyzer.ts +388 -0
- package/src/plugins/analysis/ServiceLayerAnalyzer.ts +429 -0
- package/src/plugins/analysis/SocketIOAnalyzer.ts +395 -0
- package/src/plugins/analysis/SystemDbAnalyzer.ts +284 -0
- package/src/plugins/analysis/ast/ConditionParser.ts +333 -0
- package/src/plugins/analysis/ast/ExpressionEvaluator.ts +117 -0
- package/src/plugins/analysis/ast/GraphBuilder.ts +1371 -0
- package/src/plugins/analysis/ast/OxcAdapter.ts +63 -0
- package/src/plugins/analysis/ast/types.ts +400 -0
- package/src/plugins/analysis/ast/visitors/ASTVisitor.ts +137 -0
- package/src/plugins/analysis/ast/visitors/CallExpressionVisitor.ts +528 -0
- package/src/plugins/analysis/ast/visitors/ClassVisitor.ts +339 -0
- package/src/plugins/analysis/ast/visitors/FunctionVisitor.ts +273 -0
- package/src/plugins/analysis/ast/visitors/ImportExportVisitor.ts +259 -0
- package/src/plugins/analysis/ast/visitors/TypeScriptVisitor.ts +235 -0
- package/src/plugins/analysis/ast/visitors/VariableVisitor.ts +268 -0
- package/src/plugins/analysis/ast/visitors/index.ts +36 -0
- package/src/plugins/discovery/DiscoveryPlugin.ts +50 -0
- package/src/plugins/discovery/MonorepoServiceDiscovery.ts +117 -0
- package/src/plugins/discovery/SimpleProjectDiscovery.ts +102 -0
- package/src/plugins/enrichment/AliasTracker.ts +399 -0
- package/src/plugins/enrichment/HTTPConnectionEnricher.ts +192 -0
- package/src/plugins/enrichment/ImportExportLinker.ts +221 -0
- package/src/plugins/enrichment/InstanceOfResolver.ts +165 -0
- package/src/plugins/enrichment/MethodCallResolver.ts +333 -0
- package/src/plugins/enrichment/MountPointResolver.ts +264 -0
- package/src/plugins/enrichment/PrefixEvaluator.ts +527 -0
- package/src/plugins/enrichment/RustFFIEnricher.ts +218 -0
- package/src/plugins/enrichment/ValueDomainAnalyzer.ts +682 -0
- package/src/plugins/indexing/IncrementalModuleIndexer.ts +287 -0
- package/src/plugins/indexing/JSModuleIndexer.ts +374 -0
- package/src/plugins/indexing/RustModuleIndexer.ts +160 -0
- package/src/plugins/indexing/ServiceDetector.ts +230 -0
- package/src/plugins/validation/CallResolverValidator.ts +170 -0
- package/src/plugins/validation/DataFlowValidator.ts +233 -0
- package/src/plugins/validation/EvalBanValidator.ts +175 -0
- package/src/plugins/validation/GraphConnectivityValidator.ts +201 -0
- package/src/plugins/validation/SQLInjectionValidator.ts +363 -0
- package/src/plugins/validation/ShadowingDetector.ts +173 -0
- package/src/plugins/validation/TypeScriptDeadCodeValidator.ts +203 -0
- package/src/plugins/vcs/GitPlugin.ts +344 -0
- package/src/plugins/vcs/VCSPlugin.ts +190 -0
- package/src/plugins/vcs/index.ts +32 -0
- package/src/storage/backends/RFDBServerBackend.ts +687 -0
- package/src/storage/backends/typeValidation.ts +151 -0
- package/src/validation/PathValidator.ts +342 -0
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ValueDomainAnalyzer - Value Set Analysis for computed member access
|
|
3
|
+
*
|
|
4
|
+
* Purpose: Determine the set of possible values for a variable and resolve
|
|
5
|
+
* computed member access obj[method]() when method is deterministic.
|
|
6
|
+
*
|
|
7
|
+
* USES:
|
|
8
|
+
* - VARIABLE -> ASSIGNED_FROM -> LITERAL (from JSASTAnalyzer)
|
|
9
|
+
* - VARIABLE -> ASSIGNED_FROM -> VARIABLE (transitive chains)
|
|
10
|
+
* - ConditionalExpression → multiple ASSIGNED_FROM edges
|
|
11
|
+
*
|
|
12
|
+
* CREATES:
|
|
13
|
+
* - CALL -> CALLS -> METHOD (with isConditional: true for conditional calls)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { Plugin, createSuccessResult } from '../Plugin.js';
|
|
17
|
+
import type { PluginMetadata, PluginContext, PluginResult } from '../Plugin.js';
|
|
18
|
+
import type { NodeRecord } from '@grafema/types';
|
|
19
|
+
import type { EdgeRecord } from '@grafema/types';
|
|
20
|
+
|
|
21
|
+
interface ComputedCallNode {
|
|
22
|
+
id: string;
|
|
23
|
+
type: string;
|
|
24
|
+
name: string;
|
|
25
|
+
file: string;
|
|
26
|
+
line: number;
|
|
27
|
+
computed: boolean;
|
|
28
|
+
object?: string;
|
|
29
|
+
property?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface VariableNode {
|
|
33
|
+
id: string;
|
|
34
|
+
type: string;
|
|
35
|
+
name: string;
|
|
36
|
+
file: string;
|
|
37
|
+
line: number;
|
|
38
|
+
attrs?: {
|
|
39
|
+
name?: string;
|
|
40
|
+
file?: string;
|
|
41
|
+
};
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface ExpressionNode {
|
|
46
|
+
id: string;
|
|
47
|
+
type: string;
|
|
48
|
+
name?: string;
|
|
49
|
+
file?: string;
|
|
50
|
+
line?: number;
|
|
51
|
+
expressionType?: string;
|
|
52
|
+
object?: string;
|
|
53
|
+
property?: string;
|
|
54
|
+
attrs?: {
|
|
55
|
+
expressionType?: string;
|
|
56
|
+
object?: string;
|
|
57
|
+
property?: string;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface ScopeNode {
|
|
62
|
+
id: string;
|
|
63
|
+
type: string;
|
|
64
|
+
name?: string;
|
|
65
|
+
file?: string;
|
|
66
|
+
line?: number;
|
|
67
|
+
originalId?: string;
|
|
68
|
+
stableId?: string;
|
|
69
|
+
parentScopeId?: string;
|
|
70
|
+
constraints?: Constraint[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface Constraint {
|
|
74
|
+
variable?: string;
|
|
75
|
+
operator?: string;
|
|
76
|
+
value?: unknown;
|
|
77
|
+
values?: unknown[];
|
|
78
|
+
type?: 'or' | 'and';
|
|
79
|
+
constraints?: Constraint[];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface ValueSetResult {
|
|
83
|
+
values: unknown[];
|
|
84
|
+
hasUnknown: boolean;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface ValueSetAtNodeResult extends ValueSetResult {
|
|
88
|
+
constraints: Constraint[];
|
|
89
|
+
globalValues: unknown[];
|
|
90
|
+
globalHasUnknown: boolean;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
interface NondeterministicPattern {
|
|
94
|
+
object: string;
|
|
95
|
+
property: string;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface Graph {
|
|
99
|
+
queryNodes(filter: { nodeType: string }): AsyncIterable<NodeRecord>;
|
|
100
|
+
getNode(id: string): Promise<NodeRecord | null>;
|
|
101
|
+
getOutgoingEdges(nodeId: string): Promise<EdgeRecord[]>;
|
|
102
|
+
getIncomingEdges(nodeId: string): Promise<EdgeRecord[]>;
|
|
103
|
+
addEdge(edge: { src: string; dst: string; type: string; metadata?: Record<string, unknown> }): Promise<void> | void;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
interface ProgressCallback {
|
|
107
|
+
(info: {
|
|
108
|
+
phase: string;
|
|
109
|
+
currentPlugin: string;
|
|
110
|
+
message: string;
|
|
111
|
+
totalFiles: number;
|
|
112
|
+
processedFiles: number;
|
|
113
|
+
}): void;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export class ValueDomainAnalyzer extends Plugin {
|
|
117
|
+
static MAX_DEPTH = 10; // Maximum depth for tracing
|
|
118
|
+
|
|
119
|
+
// Nondeterministic MemberExpression patterns
|
|
120
|
+
// object.property patterns that are external/user input
|
|
121
|
+
static NONDETERMINISTIC_PATTERNS: NondeterministicPattern[] = [
|
|
122
|
+
// Environment variables
|
|
123
|
+
{ object: 'process', property: 'env' },
|
|
124
|
+
// HTTP request data (Express.js patterns)
|
|
125
|
+
{ object: 'req', property: 'body' },
|
|
126
|
+
{ object: 'req', property: 'query' },
|
|
127
|
+
{ object: 'req', property: 'params' },
|
|
128
|
+
{ object: 'req', property: 'headers' },
|
|
129
|
+
{ object: 'req', property: 'cookies' },
|
|
130
|
+
{ object: 'request', property: 'body' },
|
|
131
|
+
{ object: 'request', property: 'query' },
|
|
132
|
+
{ object: 'request', property: 'params' },
|
|
133
|
+
// Context patterns (Koa, etc.)
|
|
134
|
+
{ object: 'ctx', property: 'request' },
|
|
135
|
+
{ object: 'ctx', property: 'body' },
|
|
136
|
+
{ object: 'ctx', property: 'query' },
|
|
137
|
+
{ object: 'ctx', property: 'params' },
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
// Nondeterministic object prefixes (any property access is nondeterministic)
|
|
141
|
+
static NONDETERMINISTIC_OBJECTS: string[] = [
|
|
142
|
+
'process.env', // process.env.ANY_VAR
|
|
143
|
+
'req.body', // req.body.userId
|
|
144
|
+
'req.query', // req.query.filter
|
|
145
|
+
'req.params', // req.params.id
|
|
146
|
+
'request.body',
|
|
147
|
+
'ctx.request',
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
get metadata(): PluginMetadata {
|
|
151
|
+
return {
|
|
152
|
+
name: 'ValueDomainAnalyzer',
|
|
153
|
+
phase: 'ENRICHMENT',
|
|
154
|
+
priority: 65, // After AliasTracker (60)
|
|
155
|
+
creates: {
|
|
156
|
+
nodes: [],
|
|
157
|
+
edges: ['CALLS']
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async execute(context: PluginContext): Promise<PluginResult> {
|
|
163
|
+
const { graph } = context;
|
|
164
|
+
const onProgress = (context as unknown as { onProgress?: ProgressCallback }).onProgress;
|
|
165
|
+
const graphTyped = graph as unknown as Graph;
|
|
166
|
+
|
|
167
|
+
console.log('[ValueDomainAnalyzer] Starting value domain analysis...');
|
|
168
|
+
|
|
169
|
+
let callsProcessed = 0;
|
|
170
|
+
let callsResolved = 0;
|
|
171
|
+
let edgesCreated = 0;
|
|
172
|
+
let conditionalCalls = 0;
|
|
173
|
+
let partialCalls = 0;
|
|
174
|
+
|
|
175
|
+
// 1. Find all CALL nodes with computed member access
|
|
176
|
+
const computedCalls: ComputedCallNode[] = [];
|
|
177
|
+
for await (const node of graphTyped.queryNodes({ nodeType: 'CALL' })) {
|
|
178
|
+
// Cast through unknown since node types vary
|
|
179
|
+
const callNode = node as unknown as ComputedCallNode;
|
|
180
|
+
if (callNode.computed === true) {
|
|
181
|
+
computedCalls.push(callNode);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
console.log(`[ValueDomainAnalyzer] Found ${computedCalls.length} computed member calls`);
|
|
186
|
+
|
|
187
|
+
// 2. For each computed call get value set
|
|
188
|
+
for (const call of computedCalls) {
|
|
189
|
+
callsProcessed++;
|
|
190
|
+
|
|
191
|
+
// Report progress every 20 calls
|
|
192
|
+
if (onProgress && callsProcessed % 20 === 0) {
|
|
193
|
+
(onProgress as ProgressCallback)({
|
|
194
|
+
phase: 'enrichment',
|
|
195
|
+
currentPlugin: 'ValueDomainAnalyzer',
|
|
196
|
+
message: `Analyzing value domains ${callsProcessed}/${computedCalls.length}`,
|
|
197
|
+
totalFiles: computedCalls.length,
|
|
198
|
+
processedFiles: callsProcessed
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const objectName = call.object;
|
|
203
|
+
const propertyExpr = call.property; // variable name with method name
|
|
204
|
+
|
|
205
|
+
if (!objectName || !propertyExpr) continue;
|
|
206
|
+
|
|
207
|
+
// 3. Get value set for property expression
|
|
208
|
+
const valueSet = await this.getValueSet(propertyExpr, call.file, graphTyped);
|
|
209
|
+
|
|
210
|
+
if (valueSet.hasUnknown && valueSet.values.length === 0) {
|
|
211
|
+
// Completely nondeterministic - skip
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (valueSet.values.length === 0) {
|
|
216
|
+
// No known values - skip
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// 4. Create CALLS edges for each known value
|
|
221
|
+
callsResolved++;
|
|
222
|
+
const isConditional = valueSet.values.length > 1 || valueSet.hasUnknown;
|
|
223
|
+
const partial = valueSet.hasUnknown;
|
|
224
|
+
|
|
225
|
+
for (const methodName of valueSet.values) {
|
|
226
|
+
// Find method by name in the same file
|
|
227
|
+
const targetMethod = await this.findMethod(objectName, methodName as string, call.file, graphTyped);
|
|
228
|
+
|
|
229
|
+
if (targetMethod) {
|
|
230
|
+
await graphTyped.addEdge({
|
|
231
|
+
src: call.id,
|
|
232
|
+
dst: targetMethod.id,
|
|
233
|
+
type: 'CALLS',
|
|
234
|
+
metadata: {
|
|
235
|
+
isConditional,
|
|
236
|
+
partial: partial || undefined, // undefined to not store false
|
|
237
|
+
source: 'computed_member_access'
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
edgesCreated++;
|
|
241
|
+
|
|
242
|
+
if (isConditional) {
|
|
243
|
+
conditionalCalls++;
|
|
244
|
+
}
|
|
245
|
+
if (partial) {
|
|
246
|
+
partialCalls++;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const summary = {
|
|
253
|
+
callsProcessed,
|
|
254
|
+
callsResolved,
|
|
255
|
+
edgesCreated,
|
|
256
|
+
conditionalCalls,
|
|
257
|
+
partialCalls
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
console.log('[ValueDomainAnalyzer] Summary:', summary);
|
|
261
|
+
|
|
262
|
+
return createSuccessResult(
|
|
263
|
+
{ nodes: 0, edges: edgesCreated },
|
|
264
|
+
summary
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Get set of possible values for a variable
|
|
270
|
+
*/
|
|
271
|
+
async getValueSet(variableName: string, file: string, graph: Graph): Promise<ValueSetResult> {
|
|
272
|
+
const result: ValueSetResult = {
|
|
273
|
+
values: [],
|
|
274
|
+
hasUnknown: false
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
// Find variable
|
|
278
|
+
const variables: VariableNode[] = [];
|
|
279
|
+
for await (const node of graph.queryNodes({ nodeType: 'VARIABLE' })) {
|
|
280
|
+
const varNode = node as VariableNode;
|
|
281
|
+
const nodeName = varNode.name || varNode.attrs?.name;
|
|
282
|
+
const nodeFile = varNode.file || varNode.attrs?.file;
|
|
283
|
+
if (nodeName === variableName && nodeFile === file) {
|
|
284
|
+
variables.push(varNode);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
for await (const node of graph.queryNodes({ nodeType: 'CONSTANT' })) {
|
|
288
|
+
const varNode = node as VariableNode;
|
|
289
|
+
const nodeName = varNode.name || varNode.attrs?.name;
|
|
290
|
+
const nodeFile = varNode.file || varNode.attrs?.file;
|
|
291
|
+
if (nodeName === variableName && nodeFile === file) {
|
|
292
|
+
variables.push(varNode);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (variables.length === 0) {
|
|
297
|
+
console.log(`[ValueDomainAnalyzer] No variable found for ${variableName} in ${file}`);
|
|
298
|
+
result.hasUnknown = true;
|
|
299
|
+
return result;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
console.log(`[ValueDomainAnalyzer] Found ${variables.length} variable(s) for ${variableName}`);
|
|
303
|
+
|
|
304
|
+
// Trace ASSIGNED_FROM to LITERAL or nondeterministic sources
|
|
305
|
+
const visited = new Set<string>();
|
|
306
|
+
const valueSet = new Set<unknown>();
|
|
307
|
+
|
|
308
|
+
for (const variable of variables) {
|
|
309
|
+
const { values, hasUnknown } = await this.traceValueSet(
|
|
310
|
+
variable,
|
|
311
|
+
graph,
|
|
312
|
+
visited,
|
|
313
|
+
0
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
values.forEach(v => valueSet.add(v));
|
|
317
|
+
if (hasUnknown) {
|
|
318
|
+
result.hasUnknown = true;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
result.values = Array.from(valueSet);
|
|
323
|
+
return result;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get value set for a variable at a specific node, considering path constraints
|
|
328
|
+
* This is path-sensitive: it collects constraints from enclosing scopes and applies them
|
|
329
|
+
*/
|
|
330
|
+
async getValueSetAtNode(
|
|
331
|
+
variableName: string,
|
|
332
|
+
node: NodeRecord & { parentScopeId?: string },
|
|
333
|
+
graph: Graph
|
|
334
|
+
): Promise<ValueSetAtNodeResult> {
|
|
335
|
+
// 1. Get global value set
|
|
336
|
+
const file = (node as { file?: string; attrs?: { file?: string } }).file ||
|
|
337
|
+
(node as { attrs?: { file?: string } }).attrs?.file || '';
|
|
338
|
+
const globalResult = await this.getValueSet(variableName, file, graph);
|
|
339
|
+
|
|
340
|
+
// 2. Collect constraints from enclosing scopes
|
|
341
|
+
const constraints = await this.collectPathConstraints(node, graph);
|
|
342
|
+
|
|
343
|
+
// 3. Filter constraints relevant to this variable
|
|
344
|
+
const relevantConstraints = constraints.filter(c =>
|
|
345
|
+
c.variable === variableName ||
|
|
346
|
+
(c.type === 'or' && c.constraints?.some(sub => sub.variable === variableName)) ||
|
|
347
|
+
(c.type === 'and' && c.constraints?.some(sub => sub.variable === variableName))
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
// 4. Apply constraints to narrow the value set
|
|
351
|
+
const refinedResult = this.applyConstraints(globalResult, relevantConstraints, variableName);
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
...refinedResult,
|
|
355
|
+
constraints: relevantConstraints,
|
|
356
|
+
globalValues: globalResult.values,
|
|
357
|
+
globalHasUnknown: globalResult.hasUnknown
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Collect all constraints from the scope chain leading to this node
|
|
363
|
+
*/
|
|
364
|
+
async collectPathConstraints(
|
|
365
|
+
node: NodeRecord & { parentScopeId?: string },
|
|
366
|
+
graph: Graph
|
|
367
|
+
): Promise<Constraint[]> {
|
|
368
|
+
const constraints: Constraint[] = [];
|
|
369
|
+
let currentScopeId = node.parentScopeId;
|
|
370
|
+
const visited = new Set<string>();
|
|
371
|
+
|
|
372
|
+
while (currentScopeId && !visited.has(currentScopeId)) {
|
|
373
|
+
visited.add(currentScopeId);
|
|
374
|
+
|
|
375
|
+
// Find the scope node
|
|
376
|
+
let scope: ScopeNode | null = null;
|
|
377
|
+
for await (const s of graph.queryNodes({ nodeType: 'SCOPE' })) {
|
|
378
|
+
const scopeNode = s as ScopeNode;
|
|
379
|
+
if (scopeNode.id === currentScopeId ||
|
|
380
|
+
scopeNode.originalId === currentScopeId ||
|
|
381
|
+
scopeNode.stableId === currentScopeId) {
|
|
382
|
+
scope = scopeNode;
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (!scope) break;
|
|
388
|
+
|
|
389
|
+
// Add constraints from this scope
|
|
390
|
+
if (scope.constraints && Array.isArray(scope.constraints)) {
|
|
391
|
+
constraints.push(...scope.constraints);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Move up to parent scope
|
|
395
|
+
currentScopeId = scope.parentScopeId;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return constraints;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Apply constraints to narrow a value set
|
|
403
|
+
*/
|
|
404
|
+
applyConstraints(
|
|
405
|
+
valueSet: ValueSetResult,
|
|
406
|
+
constraints: Constraint[],
|
|
407
|
+
variableName: string
|
|
408
|
+
): ValueSetResult {
|
|
409
|
+
if (constraints.length === 0) {
|
|
410
|
+
return valueSet;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
let result: ValueSetResult = {
|
|
414
|
+
values: [...valueSet.values],
|
|
415
|
+
hasUnknown: valueSet.hasUnknown
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
for (const constraint of constraints) {
|
|
419
|
+
result = this.applySingleConstraint(result, constraint, variableName);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return result;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Apply a single constraint to a value set
|
|
427
|
+
*/
|
|
428
|
+
applySingleConstraint(
|
|
429
|
+
valueSet: ValueSetResult,
|
|
430
|
+
constraint: Constraint,
|
|
431
|
+
variableName: string
|
|
432
|
+
): ValueSetResult {
|
|
433
|
+
if (constraint.variable !== variableName) {
|
|
434
|
+
// Constraint is for a different variable - no change
|
|
435
|
+
return valueSet;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
switch (constraint.operator) {
|
|
439
|
+
case '===':
|
|
440
|
+
case '==':
|
|
441
|
+
// Exact match - narrow to single value
|
|
442
|
+
return {
|
|
443
|
+
values: [constraint.value],
|
|
444
|
+
hasUnknown: false
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
case '!==':
|
|
448
|
+
case '!=':
|
|
449
|
+
// Exclusion - remove specific value from set
|
|
450
|
+
return {
|
|
451
|
+
values: valueSet.values.filter(v => v !== constraint.value),
|
|
452
|
+
hasUnknown: valueSet.hasUnknown
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
case 'in':
|
|
456
|
+
// Value must be one of the specified values
|
|
457
|
+
if (constraint.values) {
|
|
458
|
+
if (valueSet.hasUnknown) {
|
|
459
|
+
// Unknown narrowed to specific set
|
|
460
|
+
return {
|
|
461
|
+
values: constraint.values,
|
|
462
|
+
hasUnknown: false
|
|
463
|
+
};
|
|
464
|
+
} else {
|
|
465
|
+
// Intersect with known values
|
|
466
|
+
return {
|
|
467
|
+
values: valueSet.values.filter(v => constraint.values!.includes(v)),
|
|
468
|
+
hasUnknown: false
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return valueSet;
|
|
473
|
+
|
|
474
|
+
case 'not_in':
|
|
475
|
+
// Value must NOT be one of the specified values
|
|
476
|
+
if (constraint.values) {
|
|
477
|
+
return {
|
|
478
|
+
values: valueSet.values.filter(v => !constraint.values!.includes(v)),
|
|
479
|
+
hasUnknown: valueSet.hasUnknown
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
return valueSet;
|
|
483
|
+
|
|
484
|
+
case 'truthy':
|
|
485
|
+
// Variable is truthy - can't narrow much, but excludes falsy values
|
|
486
|
+
return {
|
|
487
|
+
values: valueSet.values.filter(v =>
|
|
488
|
+
v !== null && v !== undefined && v !== false && v !== 0 && v !== ''
|
|
489
|
+
),
|
|
490
|
+
hasUnknown: valueSet.hasUnknown
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
case 'falsy':
|
|
494
|
+
// Variable is falsy
|
|
495
|
+
return {
|
|
496
|
+
values: valueSet.values.filter(v =>
|
|
497
|
+
v === null || v === undefined || v === false || v === 0 || v === ''
|
|
498
|
+
),
|
|
499
|
+
hasUnknown: false // We know it's falsy
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
default:
|
|
503
|
+
return valueSet;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Check if an EXPRESSION node represents a nondeterministic source
|
|
509
|
+
*/
|
|
510
|
+
isNondeterministicExpression(node: ExpressionNode): boolean {
|
|
511
|
+
const expressionType = node.expressionType || node.attrs?.expressionType;
|
|
512
|
+
if (expressionType !== 'MemberExpression') {
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const object = node.object || node.attrs?.object;
|
|
517
|
+
const property = node.property || node.attrs?.property;
|
|
518
|
+
|
|
519
|
+
if (!object || !property) {
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Check exact patterns (object.property)
|
|
524
|
+
for (const pattern of ValueDomainAnalyzer.NONDETERMINISTIC_PATTERNS) {
|
|
525
|
+
if (object === pattern.object && property === pattern.property) {
|
|
526
|
+
return true;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Check if object is a known nondeterministic prefix
|
|
531
|
+
// e.g., process.env.VAR where object is 'process.env'
|
|
532
|
+
for (const prefix of ValueDomainAnalyzer.NONDETERMINISTIC_OBJECTS) {
|
|
533
|
+
if (object === prefix || object.startsWith(prefix + '.')) {
|
|
534
|
+
return true;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Recursive value set tracing through ASSIGNED_FROM edges
|
|
543
|
+
*/
|
|
544
|
+
async traceValueSet(
|
|
545
|
+
node: NodeRecord,
|
|
546
|
+
graph: Graph,
|
|
547
|
+
visited: Set<string>,
|
|
548
|
+
depth: number
|
|
549
|
+
): Promise<ValueSetResult> {
|
|
550
|
+
const result: ValueSetResult = { values: [], hasUnknown: false };
|
|
551
|
+
|
|
552
|
+
// Cycle protection
|
|
553
|
+
if (visited.has(node.id)) {
|
|
554
|
+
return result;
|
|
555
|
+
}
|
|
556
|
+
visited.add(node.id);
|
|
557
|
+
|
|
558
|
+
// Depth protection
|
|
559
|
+
if (depth > ValueDomainAnalyzer.MAX_DEPTH) {
|
|
560
|
+
result.hasUnknown = true;
|
|
561
|
+
return result;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Support both fields: nodeType (from getNode) and type (alias)
|
|
565
|
+
const nodeType = (node as { nodeType?: string; type?: string }).nodeType ||
|
|
566
|
+
(node as { type?: string }).type;
|
|
567
|
+
|
|
568
|
+
// If it's a LITERAL - add value
|
|
569
|
+
if (nodeType === 'LITERAL') {
|
|
570
|
+
const value = (node as { value?: unknown }).value;
|
|
571
|
+
if (value !== undefined && value !== null) {
|
|
572
|
+
result.values.push(value);
|
|
573
|
+
}
|
|
574
|
+
return result;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// If it's a PARAMETER or nondeterministic source
|
|
578
|
+
if (nodeType === 'PARAMETER') {
|
|
579
|
+
result.hasUnknown = true;
|
|
580
|
+
return result;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// If it's a CALL - consider nondeterministic (for now)
|
|
584
|
+
if (nodeType === 'CALL') {
|
|
585
|
+
result.hasUnknown = true;
|
|
586
|
+
return result;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// If it's an EXPRESSION - check nondeterministic patterns
|
|
590
|
+
if (nodeType === 'EXPRESSION') {
|
|
591
|
+
if (this.isNondeterministicExpression(node as ExpressionNode)) {
|
|
592
|
+
result.hasUnknown = true;
|
|
593
|
+
return result;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Follow ASSIGNED_FROM and DERIVES_FROM edges
|
|
598
|
+
// DERIVES_FROM is used for template literals and other composite expressions
|
|
599
|
+
const outgoing = await graph.getOutgoingEdges(node.id);
|
|
600
|
+
// edgeType (from getOutgoingEdges) or edge_type (from other APIs)
|
|
601
|
+
const dataFlowEdges = outgoing.filter(e => {
|
|
602
|
+
const edgeType = (e as { edgeType?: string; edge_type?: string }).edgeType ||
|
|
603
|
+
(e as { edge_type?: string }).edge_type;
|
|
604
|
+
return edgeType === 'ASSIGNED_FROM' || edgeType === 'DERIVES_FROM';
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
if (dataFlowEdges.length === 0) {
|
|
608
|
+
// No sources - unknown
|
|
609
|
+
result.hasUnknown = true;
|
|
610
|
+
return result;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// Recursively trace each source
|
|
614
|
+
for (const edge of dataFlowEdges) {
|
|
615
|
+
// dst (from getOutgoingEdges) or target_id (from other APIs)
|
|
616
|
+
const targetId = (edge as { dst?: string; target_id?: string }).dst ||
|
|
617
|
+
(edge as { target_id?: string }).target_id;
|
|
618
|
+
if (!targetId) continue;
|
|
619
|
+
|
|
620
|
+
const sourceNode = await graph.getNode(targetId);
|
|
621
|
+
if (!sourceNode) continue;
|
|
622
|
+
|
|
623
|
+
const sourceResult = await this.traceValueSet(
|
|
624
|
+
sourceNode,
|
|
625
|
+
graph,
|
|
626
|
+
visited,
|
|
627
|
+
depth + 1
|
|
628
|
+
);
|
|
629
|
+
|
|
630
|
+
sourceResult.values.forEach(v => result.values.push(v));
|
|
631
|
+
if (sourceResult.hasUnknown) {
|
|
632
|
+
result.hasUnknown = true;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return result;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Find method by object name and method name
|
|
641
|
+
*/
|
|
642
|
+
async findMethod(
|
|
643
|
+
objectName: string,
|
|
644
|
+
methodName: string,
|
|
645
|
+
file: string,
|
|
646
|
+
graph: Graph
|
|
647
|
+
): Promise<NodeRecord | null> {
|
|
648
|
+
// Find methods in the same file
|
|
649
|
+
for await (const node of graph.queryNodes({ nodeType: 'FUNCTION' })) {
|
|
650
|
+
const funcNode = node as { file?: string; name?: string };
|
|
651
|
+
if (funcNode.file === file && funcNode.name === methodName) {
|
|
652
|
+
// Check if this is a method of the right object
|
|
653
|
+
// Simplified: check via incoming CONTAINS edges from CLASS
|
|
654
|
+
const incoming = await graph.getIncomingEdges(node.id);
|
|
655
|
+
const containsEdges = incoming.filter(e => {
|
|
656
|
+
const edgeType = (e as { edgeType?: string; edge_type?: string }).edgeType ||
|
|
657
|
+
(e as { edge_type?: string }).edge_type;
|
|
658
|
+
return edgeType === 'CONTAINS';
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
for (const edge of containsEdges) {
|
|
662
|
+
const sourceId = (edge as { src?: string; source_id?: string }).src ||
|
|
663
|
+
(edge as { source_id?: string }).source_id;
|
|
664
|
+
if (!sourceId) continue;
|
|
665
|
+
|
|
666
|
+
const container = await graph.getNode(sourceId);
|
|
667
|
+
// node_type (from DB) or type (from addNodes)
|
|
668
|
+
const containerType = (container as { node_type?: string; type?: string })?.node_type ||
|
|
669
|
+
(container as { type?: string })?.type;
|
|
670
|
+
const containerName = (container as { name?: string })?.name;
|
|
671
|
+
if (container && containerType === 'CLASS' && containerName === objectName) {
|
|
672
|
+
return node;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
return null;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
export default ValueDomainAnalyzer;
|