@grafema/util 0.3.0-beta
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/dist/api/GraphAPI.d.ts +87 -0
- package/dist/api/GraphAPI.d.ts.map +1 -0
- package/dist/api/GraphAPI.js +212 -0
- package/dist/api/GraphAPI.js.map +1 -0
- package/dist/api/GuaranteeAPI.d.ts +147 -0
- package/dist/api/GuaranteeAPI.d.ts.map +1 -0
- package/dist/api/GuaranteeAPI.js +290 -0
- package/dist/api/GuaranteeAPI.js.map +1 -0
- package/dist/config/ConfigLoader.d.ts +214 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +441 -0
- package/dist/config/ConfigLoader.js.map +1 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +5 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/CoverageAnalyzer.d.ts +65 -0
- package/dist/core/CoverageAnalyzer.d.ts.map +1 -0
- package/dist/core/CoverageAnalyzer.js +199 -0
- package/dist/core/CoverageAnalyzer.js.map +1 -0
- package/dist/core/FileExplainer.d.ts +101 -0
- package/dist/core/FileExplainer.d.ts.map +1 -0
- package/dist/core/FileExplainer.js +140 -0
- package/dist/core/FileExplainer.js.map +1 -0
- package/dist/core/FileOverview.d.ts +124 -0
- package/dist/core/FileOverview.d.ts.map +1 -0
- package/dist/core/FileOverview.js +279 -0
- package/dist/core/FileOverview.js.map +1 -0
- package/dist/core/GrafemaUri.d.ts +66 -0
- package/dist/core/GrafemaUri.d.ts.map +1 -0
- package/dist/core/GrafemaUri.js +191 -0
- package/dist/core/GrafemaUri.js.map +1 -0
- package/dist/core/GraphBackend.d.ts +158 -0
- package/dist/core/GraphBackend.d.ts.map +1 -0
- package/dist/core/GraphBackend.js +85 -0
- package/dist/core/GraphBackend.js.map +1 -0
- package/dist/core/GraphFreshnessChecker.d.ts +33 -0
- package/dist/core/GraphFreshnessChecker.d.ts.map +1 -0
- package/dist/core/GraphFreshnessChecker.js +104 -0
- package/dist/core/GraphFreshnessChecker.js.map +1 -0
- package/dist/core/GuaranteeManager.d.ts +254 -0
- package/dist/core/GuaranteeManager.d.ts.map +1 -0
- package/dist/core/GuaranteeManager.js +447 -0
- package/dist/core/GuaranteeManager.js.map +1 -0
- package/dist/core/HashUtils.d.ts +24 -0
- package/dist/core/HashUtils.d.ts.map +1 -0
- package/dist/core/HashUtils.js +46 -0
- package/dist/core/HashUtils.js.map +1 -0
- package/dist/core/IncrementalReanalyzer.d.ts +33 -0
- package/dist/core/IncrementalReanalyzer.d.ts.map +1 -0
- package/dist/core/IncrementalReanalyzer.js +67 -0
- package/dist/core/IncrementalReanalyzer.js.map +1 -0
- package/dist/core/ResourceRegistry.d.ts +17 -0
- package/dist/core/ResourceRegistry.d.ts.map +1 -0
- package/dist/core/ResourceRegistry.js +32 -0
- package/dist/core/ResourceRegistry.js.map +1 -0
- package/dist/core/SemanticId.d.ts +159 -0
- package/dist/core/SemanticId.d.ts.map +1 -0
- package/dist/core/SemanticId.js +291 -0
- package/dist/core/SemanticId.js.map +1 -0
- package/dist/core/VersionManager.d.ts +166 -0
- package/dist/core/VersionManager.d.ts.map +1 -0
- package/dist/core/VersionManager.js +239 -0
- package/dist/core/VersionManager.js.map +1 -0
- package/dist/core/brandNodeInternal.d.ts +14 -0
- package/dist/core/brandNodeInternal.d.ts.map +1 -0
- package/dist/core/brandNodeInternal.js +4 -0
- package/dist/core/brandNodeInternal.js.map +1 -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 +118 -0
- package/dist/core/nodes/GuaranteeNode.js.map +1 -0
- package/dist/core/nodes/IssueNode.d.ts +73 -0
- package/dist/core/nodes/IssueNode.d.ts.map +1 -0
- package/dist/core/nodes/IssueNode.js +130 -0
- package/dist/core/nodes/IssueNode.js.map +1 -0
- package/dist/core/nodes/NodeKind.d.ts +104 -0
- package/dist/core/nodes/NodeKind.d.ts.map +1 -0
- package/dist/core/nodes/NodeKind.js +166 -0
- package/dist/core/nodes/NodeKind.js.map +1 -0
- package/dist/diagnostics/DiagnosticCollector.d.ts +103 -0
- package/dist/diagnostics/DiagnosticCollector.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticCollector.js +133 -0
- package/dist/diagnostics/DiagnosticCollector.js.map +1 -0
- package/dist/diagnostics/DiagnosticReporter.d.ts +122 -0
- package/dist/diagnostics/DiagnosticReporter.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticReporter.js +300 -0
- package/dist/diagnostics/DiagnosticReporter.js.map +1 -0
- package/dist/diagnostics/DiagnosticWriter.d.ts +31 -0
- package/dist/diagnostics/DiagnosticWriter.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticWriter.js +44 -0
- package/dist/diagnostics/DiagnosticWriter.js.map +1 -0
- package/dist/diagnostics/categories.d.ts +57 -0
- package/dist/diagnostics/categories.d.ts.map +1 -0
- package/dist/diagnostics/categories.js +71 -0
- package/dist/diagnostics/categories.js.map +1 -0
- package/dist/diagnostics/index.d.ts +17 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/index.js +15 -0
- package/dist/diagnostics/index.js.map +1 -0
- package/dist/errors/GrafemaError.d.ts +200 -0
- package/dist/errors/GrafemaError.d.ts.map +1 -0
- package/dist/errors/GrafemaError.js +209 -0
- package/dist/errors/GrafemaError.js.map +1 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions/index.d.ts +8 -0
- package/dist/instructions/index.d.ts.map +1 -0
- package/dist/instructions/index.js +20 -0
- package/dist/instructions/index.js.map +1 -0
- package/dist/instructions/onboarding.md +133 -0
- package/dist/knowledge/KnowledgeBase.d.ts +113 -0
- package/dist/knowledge/KnowledgeBase.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeBase.js +420 -0
- package/dist/knowledge/KnowledgeBase.js.map +1 -0
- package/dist/knowledge/SemanticAddressResolver.d.ts +59 -0
- package/dist/knowledge/SemanticAddressResolver.d.ts.map +1 -0
- package/dist/knowledge/SemanticAddressResolver.js +160 -0
- package/dist/knowledge/SemanticAddressResolver.js.map +1 -0
- package/dist/knowledge/git-ingest.d.ts +58 -0
- package/dist/knowledge/git-ingest.d.ts.map +1 -0
- package/dist/knowledge/git-ingest.js +301 -0
- package/dist/knowledge/git-ingest.js.map +1 -0
- package/dist/knowledge/git-queries.d.ts +86 -0
- package/dist/knowledge/git-queries.d.ts.map +1 -0
- package/dist/knowledge/git-queries.js +177 -0
- package/dist/knowledge/git-queries.js.map +1 -0
- package/dist/knowledge/index.d.ts +14 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +10 -0
- package/dist/knowledge/index.js.map +1 -0
- package/dist/knowledge/parser.d.ts +39 -0
- package/dist/knowledge/parser.d.ts.map +1 -0
- package/dist/knowledge/parser.js +292 -0
- package/dist/knowledge/parser.js.map +1 -0
- package/dist/knowledge/types.d.ts +133 -0
- package/dist/knowledge/types.d.ts.map +1 -0
- package/dist/knowledge/types.js +8 -0
- package/dist/knowledge/types.js.map +1 -0
- package/dist/logging/Logger.d.ts +98 -0
- package/dist/logging/Logger.d.ts.map +1 -0
- package/dist/logging/Logger.js +274 -0
- package/dist/logging/Logger.js.map +1 -0
- package/dist/notation/archetypes.d.ts +36 -0
- package/dist/notation/archetypes.d.ts.map +1 -0
- package/dist/notation/archetypes.js +173 -0
- package/dist/notation/archetypes.js.map +1 -0
- package/dist/notation/fold.d.ts +25 -0
- package/dist/notation/fold.d.ts.map +1 -0
- package/dist/notation/fold.js +598 -0
- package/dist/notation/fold.js.map +1 -0
- package/dist/notation/index.d.ts +18 -0
- package/dist/notation/index.d.ts.map +1 -0
- package/dist/notation/index.js +16 -0
- package/dist/notation/index.js.map +1 -0
- package/dist/notation/lodExtractor.d.ts +32 -0
- package/dist/notation/lodExtractor.d.ts.map +1 -0
- package/dist/notation/lodExtractor.js +149 -0
- package/dist/notation/lodExtractor.js.map +1 -0
- package/dist/notation/nameShortener.d.ts +22 -0
- package/dist/notation/nameShortener.d.ts.map +1 -0
- package/dist/notation/nameShortener.js +24 -0
- package/dist/notation/nameShortener.js.map +1 -0
- package/dist/notation/perspectives.d.ts +11 -0
- package/dist/notation/perspectives.d.ts.map +1 -0
- package/dist/notation/perspectives.js +16 -0
- package/dist/notation/perspectives.js.map +1 -0
- package/dist/notation/renderer.d.ts +31 -0
- package/dist/notation/renderer.d.ts.map +1 -0
- package/dist/notation/renderer.js +315 -0
- package/dist/notation/renderer.js.map +1 -0
- package/dist/notation/traceRenderer.d.ts +39 -0
- package/dist/notation/traceRenderer.d.ts.map +1 -0
- package/dist/notation/traceRenderer.js +358 -0
- package/dist/notation/traceRenderer.js.map +1 -0
- package/dist/notation/types.d.ts +66 -0
- package/dist/notation/types.d.ts.map +1 -0
- package/dist/notation/types.js +10 -0
- package/dist/notation/types.js.map +1 -0
- package/dist/queries/NodeContext.d.ts +81 -0
- package/dist/queries/NodeContext.d.ts.map +1 -0
- package/dist/queries/NodeContext.js +196 -0
- package/dist/queries/NodeContext.js.map +1 -0
- package/dist/queries/findCallsInFunction.d.ts +62 -0
- package/dist/queries/findCallsInFunction.d.ts.map +1 -0
- package/dist/queries/findCallsInFunction.js +169 -0
- package/dist/queries/findCallsInFunction.js.map +1 -0
- package/dist/queries/findContainingFunction.d.ts +57 -0
- package/dist/queries/findContainingFunction.d.ts.map +1 -0
- package/dist/queries/findContainingFunction.js +91 -0
- package/dist/queries/findContainingFunction.js.map +1 -0
- package/dist/queries/index.d.ts +18 -0
- package/dist/queries/index.d.ts.map +1 -0
- package/dist/queries/index.js +14 -0
- package/dist/queries/index.js.map +1 -0
- package/dist/queries/traceDataflow.d.ts +65 -0
- package/dist/queries/traceDataflow.d.ts.map +1 -0
- package/dist/queries/traceDataflow.js +754 -0
- package/dist/queries/traceDataflow.js.map +1 -0
- package/dist/queries/traceValues.d.ts +70 -0
- package/dist/queries/traceValues.d.ts.map +1 -0
- package/dist/queries/traceValues.js +373 -0
- package/dist/queries/traceValues.js.map +1 -0
- package/dist/queries/types.d.ts +166 -0
- package/dist/queries/types.d.ts.map +1 -0
- package/dist/queries/types.js +10 -0
- package/dist/queries/types.js.map +1 -0
- package/dist/schema/GraphSchemaExtractor.d.ts +53 -0
- package/dist/schema/GraphSchemaExtractor.d.ts.map +1 -0
- package/dist/schema/GraphSchemaExtractor.js +125 -0
- package/dist/schema/GraphSchemaExtractor.js.map +1 -0
- package/dist/schema/InterfaceSchemaExtractor.d.ts +73 -0
- package/dist/schema/InterfaceSchemaExtractor.d.ts.map +1 -0
- package/dist/schema/InterfaceSchemaExtractor.js +113 -0
- package/dist/schema/InterfaceSchemaExtractor.js.map +1 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +3 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/storage/backends/RFDBServerBackend.d.ts +356 -0
- package/dist/storage/backends/RFDBServerBackend.d.ts.map +1 -0
- package/dist/storage/backends/RFDBServerBackend.js +748 -0
- package/dist/storage/backends/RFDBServerBackend.js.map +1 -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 +141 -0
- package/dist/storage/backends/typeValidation.js.map +1 -0
- package/dist/utils/findRfdbBinary.d.ts +67 -0
- package/dist/utils/findRfdbBinary.d.ts.map +1 -0
- package/dist/utils/findRfdbBinary.js +261 -0
- package/dist/utils/findRfdbBinary.js.map +1 -0
- package/dist/utils/lazyDownload.d.ts +43 -0
- package/dist/utils/lazyDownload.d.ts.map +1 -0
- package/dist/utils/lazyDownload.js +175 -0
- package/dist/utils/lazyDownload.js.map +1 -0
- package/dist/utils/moduleResolution.d.ts +134 -0
- package/dist/utils/moduleResolution.d.ts.map +1 -0
- package/dist/utils/moduleResolution.js +189 -0
- package/dist/utils/moduleResolution.js.map +1 -0
- package/dist/utils/resolveNodeFile.d.ts +13 -0
- package/dist/utils/resolveNodeFile.d.ts.map +1 -0
- package/dist/utils/resolveNodeFile.js +18 -0
- package/dist/utils/resolveNodeFile.js.map +1 -0
- package/dist/utils/startRfdbServer.d.ts +63 -0
- package/dist/utils/startRfdbServer.d.ts.map +1 -0
- package/dist/utils/startRfdbServer.js +142 -0
- package/dist/utils/startRfdbServer.js.map +1 -0
- package/dist/validation/PathValidator.d.ts +80 -0
- package/dist/validation/PathValidator.d.ts.map +1 -0
- package/dist/validation/PathValidator.js +252 -0
- package/dist/validation/PathValidator.js.map +1 -0
- package/dist/version.d.ts +11 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +26 -0
- package/dist/version.js.map +1 -0
- package/package.json +50 -0
- package/src/api/GraphAPI.ts +307 -0
- package/src/api/GuaranteeAPI.ts +402 -0
- package/src/config/ConfigLoader.ts +653 -0
- package/src/config/index.ts +13 -0
- package/src/core/CoverageAnalyzer.ts +243 -0
- package/src/core/FileExplainer.ts +179 -0
- package/src/core/FileOverview.ts +397 -0
- package/src/core/GrafemaUri.ts +216 -0
- package/src/core/GraphBackend.ts +266 -0
- package/src/core/GraphFreshnessChecker.ts +145 -0
- package/src/core/GuaranteeManager.ts +684 -0
- package/src/core/HashUtils.ts +48 -0
- package/src/core/IncrementalReanalyzer.ts +106 -0
- package/src/core/ResourceRegistry.ts +39 -0
- package/src/core/SemanticId.ts +423 -0
- package/src/core/VersionManager.ts +405 -0
- package/src/core/brandNodeInternal.ts +16 -0
- package/src/core/nodes/GuaranteeNode.ts +162 -0
- package/src/core/nodes/IssueNode.ts +177 -0
- package/src/core/nodes/NodeKind.ts +192 -0
- package/src/diagnostics/DiagnosticCollector.ts +170 -0
- package/src/diagnostics/DiagnosticReporter.ts +395 -0
- package/src/diagnostics/DiagnosticWriter.ts +50 -0
- package/src/diagnostics/categories.ts +104 -0
- package/src/diagnostics/index.ts +30 -0
- package/src/errors/GrafemaError.ts +297 -0
- package/src/index.ts +261 -0
- package/src/instructions/index.ts +21 -0
- package/src/instructions/onboarding.md +133 -0
- package/src/knowledge/KnowledgeBase.ts +486 -0
- package/src/knowledge/SemanticAddressResolver.ts +191 -0
- package/src/knowledge/git-ingest.ts +402 -0
- package/src/knowledge/git-queries.ts +269 -0
- package/src/knowledge/index.ts +29 -0
- package/src/knowledge/parser.ts +294 -0
- package/src/knowledge/types.ts +146 -0
- package/src/logging/Logger.ts +303 -0
- package/src/notation/archetypes.ts +189 -0
- package/src/notation/fold.ts +696 -0
- package/src/notation/index.ts +27 -0
- package/src/notation/lodExtractor.ts +177 -0
- package/src/notation/nameShortener.ts +24 -0
- package/src/notation/perspectives.ts +18 -0
- package/src/notation/renderer.ts +394 -0
- package/src/notation/traceRenderer.ts +458 -0
- package/src/notation/types.ts +79 -0
- package/src/queries/NodeContext.ts +280 -0
- package/src/queries/findCallsInFunction.ts +249 -0
- package/src/queries/findContainingFunction.ts +124 -0
- package/src/queries/index.ts +44 -0
- package/src/queries/traceDataflow.ts +838 -0
- package/src/queries/traceValues.ts +531 -0
- package/src/queries/types.ts +191 -0
- package/src/schema/GraphSchemaExtractor.ts +177 -0
- package/src/schema/InterfaceSchemaExtractor.ts +173 -0
- package/src/schema/index.ts +5 -0
- package/src/storage/backends/RFDBServerBackend.ts +895 -0
- package/src/storage/backends/typeValidation.ts +154 -0
- package/src/utils/findRfdbBinary.ts +288 -0
- package/src/utils/lazyDownload.ts +206 -0
- package/src/utils/moduleResolution.ts +271 -0
- package/src/utils/resolveNodeFile.ts +18 -0
- package/src/utils/startRfdbServer.ts +197 -0
- package/src/validation/PathValidator.ts +334 -0
- package/src/version.ts +28 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LOD (Level of Detail) Subgraph Extractor
|
|
3
|
+
*
|
|
4
|
+
* Extracts a SubgraphData from the graph backend using BFS from a root node.
|
|
5
|
+
* Different depth levels control how much of the graph neighborhood is fetched.
|
|
6
|
+
*
|
|
7
|
+
* - LOD 0: Root + direct containment children (names only in renderer)
|
|
8
|
+
* - LOD 1: Same + outgoing non-containment edges for each child, resolved targets
|
|
9
|
+
* - LOD 2: Same + expand children that have their own CONTAINS children
|
|
10
|
+
*
|
|
11
|
+
* @module notation/lodExtractor
|
|
12
|
+
*/
|
|
13
|
+
import type { BaseNodeRecord, EdgeRecord } from '@grafema/types';
|
|
14
|
+
import type { SubgraphData } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Minimal backend interface — matches the project pattern of loose coupling.
|
|
17
|
+
*/
|
|
18
|
+
interface GraphBackend {
|
|
19
|
+
getNode(id: string): Promise<BaseNodeRecord | null>;
|
|
20
|
+
getOutgoingEdges(nodeId: string, edgeTypes?: string[] | null): Promise<EdgeRecord[]>;
|
|
21
|
+
getIncomingEdges(nodeId: string, edgeTypes?: string[] | null): Promise<EdgeRecord[]>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Extract a subgraph from the backend, rooted at the given node.
|
|
25
|
+
*
|
|
26
|
+
* @param backend Graph backend
|
|
27
|
+
* @param rootNodeId Semantic ID of the root node
|
|
28
|
+
* @param depth LOD level (0, 1, or 2)
|
|
29
|
+
*/
|
|
30
|
+
export declare function extractSubgraph(backend: GraphBackend, rootNodeId: string, depth?: number): Promise<SubgraphData>;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=lodExtractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lodExtractor.d.ts","sourceRoot":"","sources":["../../src/notation/lodExtractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C;;GAEG;AACH,UAAU,YAAY;IACpB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACpD,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACrF,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CACtF;AAYD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,YAAY,CAAC,CAqFvB"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LOD (Level of Detail) Subgraph Extractor
|
|
3
|
+
*
|
|
4
|
+
* Extracts a SubgraphData from the graph backend using BFS from a root node.
|
|
5
|
+
* Different depth levels control how much of the graph neighborhood is fetched.
|
|
6
|
+
*
|
|
7
|
+
* - LOD 0: Root + direct containment children (names only in renderer)
|
|
8
|
+
* - LOD 1: Same + outgoing non-containment edges for each child, resolved targets
|
|
9
|
+
* - LOD 2: Same + expand children that have their own CONTAINS children
|
|
10
|
+
*
|
|
11
|
+
* @module notation/lodExtractor
|
|
12
|
+
*/
|
|
13
|
+
import { lookupEdge } from './archetypes.js';
|
|
14
|
+
/**
|
|
15
|
+
* Containment edge types that define the nesting tree.
|
|
16
|
+
*/
|
|
17
|
+
const CONTAINMENT_TYPES = [
|
|
18
|
+
'CONTAINS', 'HAS_SCOPE', 'HAS_MEMBER', 'HAS_BODY',
|
|
19
|
+
'HAS_PROPERTY', 'HAS_ELEMENT', 'HAS_INIT', 'HAS_UPDATE',
|
|
20
|
+
'HAS_CALLBACK', 'HAS_CATCH', 'HAS_FINALLY',
|
|
21
|
+
'DECLARES', 'DEFINES', 'MOUNTS', 'PROPERTY_KEY', 'PROPERTY_VALUE',
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* Extract a subgraph from the backend, rooted at the given node.
|
|
25
|
+
*
|
|
26
|
+
* @param backend Graph backend
|
|
27
|
+
* @param rootNodeId Semantic ID of the root node
|
|
28
|
+
* @param depth LOD level (0, 1, or 2)
|
|
29
|
+
*/
|
|
30
|
+
export async function extractSubgraph(backend, rootNodeId, depth = 1) {
|
|
31
|
+
const nodeMap = new Map();
|
|
32
|
+
const allEdges = [];
|
|
33
|
+
const root = await backend.getNode(rootNodeId);
|
|
34
|
+
if (!root) {
|
|
35
|
+
return { rootNodes: [], edges: [], nodeMap };
|
|
36
|
+
}
|
|
37
|
+
nodeMap.set(root.id, root);
|
|
38
|
+
// Step 1: Get direct containment children
|
|
39
|
+
const containmentEdges = await backend.getOutgoingEdges(rootNodeId, CONTAINMENT_TYPES);
|
|
40
|
+
const childIds = [];
|
|
41
|
+
for (const edge of containmentEdges) {
|
|
42
|
+
allEdges.push(edge);
|
|
43
|
+
childIds.push(edge.dst);
|
|
44
|
+
if (!nodeMap.has(edge.dst)) {
|
|
45
|
+
const child = await backend.getNode(edge.dst);
|
|
46
|
+
if (child)
|
|
47
|
+
nodeMap.set(child.id, child);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// LOD 0: stop here (renderer shows names only)
|
|
51
|
+
if (depth <= 0) {
|
|
52
|
+
return { rootNodes: [root], edges: allEdges, nodeMap };
|
|
53
|
+
}
|
|
54
|
+
// Step 2: For each child (and root), get outgoing non-containment edges
|
|
55
|
+
const nodesToExpand = [rootNodeId, ...childIds];
|
|
56
|
+
for (const nodeId of nodesToExpand) {
|
|
57
|
+
const outgoing = await backend.getOutgoingEdges(nodeId);
|
|
58
|
+
for (const edge of outgoing) {
|
|
59
|
+
const mapping = lookupEdge(edge.type);
|
|
60
|
+
if (mapping.archetype === 'contains')
|
|
61
|
+
continue; // already handled
|
|
62
|
+
allEdges.push(edge);
|
|
63
|
+
// Resolve target nodes
|
|
64
|
+
if (!nodeMap.has(edge.dst)) {
|
|
65
|
+
const target = await backend.getNode(edge.dst);
|
|
66
|
+
if (target)
|
|
67
|
+
nodeMap.set(target.id, target);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// LOD 1: stop here
|
|
72
|
+
if (depth <= 1) {
|
|
73
|
+
return { rootNodes: [root], edges: allEdges, nodeMap };
|
|
74
|
+
}
|
|
75
|
+
// Step 3 (LOD 2): Expand children that have their own containment children
|
|
76
|
+
for (const childId of childIds) {
|
|
77
|
+
const childContainment = await backend.getOutgoingEdges(childId, CONTAINMENT_TYPES);
|
|
78
|
+
for (const edge of childContainment) {
|
|
79
|
+
allEdges.push(edge);
|
|
80
|
+
if (!nodeMap.has(edge.dst)) {
|
|
81
|
+
const grandchild = await backend.getNode(edge.dst);
|
|
82
|
+
if (grandchild)
|
|
83
|
+
nodeMap.set(grandchild.id, grandchild);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Also get operator edges for grandchildren
|
|
87
|
+
const grandchildIds = childContainment.map(e => e.dst);
|
|
88
|
+
for (const gcId of grandchildIds) {
|
|
89
|
+
const gcOutgoing = await backend.getOutgoingEdges(gcId);
|
|
90
|
+
for (const edge of gcOutgoing) {
|
|
91
|
+
const mapping = lookupEdge(edge.type);
|
|
92
|
+
if (mapping.archetype === 'contains')
|
|
93
|
+
continue;
|
|
94
|
+
allEdges.push(edge);
|
|
95
|
+
if (!nodeMap.has(edge.dst)) {
|
|
96
|
+
const target = await backend.getNode(edge.dst);
|
|
97
|
+
if (target)
|
|
98
|
+
nodeMap.set(target.id, target);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Step 4: Fetch incoming PASSES_ARGUMENT edges for anonymous functions
|
|
104
|
+
// so the renderer can resolve λ names via callback context.
|
|
105
|
+
// CALL nodes are often not in the containment tree, so their outgoing
|
|
106
|
+
// PASSES_ARGUMENT edges don't get picked up by the BFS above.
|
|
107
|
+
await fetchCallbackContext(backend, allEdges, nodeMap);
|
|
108
|
+
return { rootNodes: [root], edges: allEdges, nodeMap };
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* For each anonymous arrow/expression in nodeMap, fetch incoming
|
|
112
|
+
* PASSES_ARGUMENT edges and resolve the CALL source node + sibling args.
|
|
113
|
+
*/
|
|
114
|
+
async function fetchCallbackContext(backend, allEdges, nodeMap) {
|
|
115
|
+
const edgeSet = new Set(allEdges.map(e => `${e.src}|${e.dst}|${e.type}`));
|
|
116
|
+
for (const node of nodeMap.values()) {
|
|
117
|
+
if (node.name !== '<arrow>' && node.name !== '<expression>')
|
|
118
|
+
continue;
|
|
119
|
+
const incoming = await backend.getIncomingEdges(node.id, ['PASSES_ARGUMENT']);
|
|
120
|
+
for (const edge of incoming) {
|
|
121
|
+
const key = `${edge.src}|${edge.dst}|${edge.type}`;
|
|
122
|
+
if (edgeSet.has(key))
|
|
123
|
+
continue;
|
|
124
|
+
edgeSet.add(key);
|
|
125
|
+
allEdges.push(edge);
|
|
126
|
+
// Resolve the CALL node (edge source)
|
|
127
|
+
if (!nodeMap.has(edge.src)) {
|
|
128
|
+
const callNode = await backend.getNode(edge.src);
|
|
129
|
+
if (callNode)
|
|
130
|
+
nodeMap.set(callNode.id, callNode);
|
|
131
|
+
}
|
|
132
|
+
// Fetch all PASSES_ARGUMENT from same CALL to find sibling args
|
|
133
|
+
const callOutgoing = await backend.getOutgoingEdges(edge.src, ['PASSES_ARGUMENT']);
|
|
134
|
+
for (const sibEdge of callOutgoing) {
|
|
135
|
+
const sibKey = `${sibEdge.src}|${sibEdge.dst}|${sibEdge.type}`;
|
|
136
|
+
if (edgeSet.has(sibKey))
|
|
137
|
+
continue;
|
|
138
|
+
edgeSet.add(sibKey);
|
|
139
|
+
allEdges.push(sibEdge);
|
|
140
|
+
if (!nodeMap.has(sibEdge.dst)) {
|
|
141
|
+
const sibNode = await backend.getNode(sibEdge.dst);
|
|
142
|
+
if (sibNode)
|
|
143
|
+
nodeMap.set(sibNode.id, sibNode);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=lodExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lodExtractor.js","sourceRoot":"","sources":["../../src/notation/lodExtractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Name Shortener — shortest-unambiguous-name within scope
|
|
3
|
+
*
|
|
4
|
+
* Given a set of display names in a subgraph, shorten them to the
|
|
5
|
+
* minimum unique suffix. For example:
|
|
6
|
+
*
|
|
7
|
+
* auth/login.ts -> UserDB.findByEmail → UserDB.findByEmail
|
|
8
|
+
* auth/login.ts -> createToken → createToken
|
|
9
|
+
* auth/utils.ts -> createToken → utils:createToken
|
|
10
|
+
*
|
|
11
|
+
* Phase 4 feature — placeholder for future implementation.
|
|
12
|
+
*
|
|
13
|
+
* @module notation/nameShortener
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Shorten a display name to its shortest unambiguous form
|
|
17
|
+
* within the given set of all names.
|
|
18
|
+
*
|
|
19
|
+
* Current implementation: return name as-is (no shortening).
|
|
20
|
+
*/
|
|
21
|
+
export declare function shortenName(name: string, _allNames: string[]): string;
|
|
22
|
+
//# sourceMappingURL=nameShortener.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nameShortener.d.ts","sourceRoot":"","sources":["../../src/notation/nameShortener.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Name Shortener — shortest-unambiguous-name within scope
|
|
3
|
+
*
|
|
4
|
+
* Given a set of display names in a subgraph, shorten them to the
|
|
5
|
+
* minimum unique suffix. For example:
|
|
6
|
+
*
|
|
7
|
+
* auth/login.ts -> UserDB.findByEmail → UserDB.findByEmail
|
|
8
|
+
* auth/login.ts -> createToken → createToken
|
|
9
|
+
* auth/utils.ts -> createToken → utils:createToken
|
|
10
|
+
*
|
|
11
|
+
* Phase 4 feature — placeholder for future implementation.
|
|
12
|
+
*
|
|
13
|
+
* @module notation/nameShortener
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Shorten a display name to its shortest unambiguous form
|
|
17
|
+
* within the given set of all names.
|
|
18
|
+
*
|
|
19
|
+
* Current implementation: return name as-is (no shortening).
|
|
20
|
+
*/
|
|
21
|
+
export function shortenName(name, _allNames) {
|
|
22
|
+
return name;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=nameShortener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nameShortener.js","sourceRoot":"","sources":["../../src/notation/nameShortener.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,SAAmB;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perspective Presets — archetype filters for describe tool
|
|
3
|
+
*
|
|
4
|
+
* Shared between MCP and CLI to keep perspectives in sync.
|
|
5
|
+
*
|
|
6
|
+
* @module notation/perspectives
|
|
7
|
+
*/
|
|
8
|
+
import type { Archetype } from './types.js';
|
|
9
|
+
/** Perspective presets map to archetype filters */
|
|
10
|
+
export declare const PERSPECTIVES: Record<string, Archetype[]>;
|
|
11
|
+
//# sourceMappingURL=perspectives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perspectives.d.ts","sourceRoot":"","sources":["../../src/notation/perspectives.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,mDAAmD;AACnD,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAMpD,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perspective Presets — archetype filters for describe tool
|
|
3
|
+
*
|
|
4
|
+
* Shared between MCP and CLI to keep perspectives in sync.
|
|
5
|
+
*
|
|
6
|
+
* @module notation/perspectives
|
|
7
|
+
*/
|
|
8
|
+
/** Perspective presets map to archetype filters */
|
|
9
|
+
export const PERSPECTIVES = {
|
|
10
|
+
security: ['write', 'exception'],
|
|
11
|
+
data: ['flow_out', 'flow_in', 'write'],
|
|
12
|
+
errors: ['exception'],
|
|
13
|
+
api: ['flow_out', 'publishes', 'depends'],
|
|
14
|
+
events: ['publishes'],
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=perspectives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perspectives.js","sourceRoot":"","sources":["../../src/notation/perspectives.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,mDAAmD;AACnD,MAAM,CAAC,MAAM,YAAY,GAAgC;IACvD,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC;IAChC,IAAI,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC;IACtC,MAAM,EAAE,CAAC,WAAW,CAAC;IACrB,GAAG,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,SAAS,CAAC;IACzC,MAAM,EAAE,CAAC,WAAW,CAAC;CACtB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notation Renderer — pure function: SubgraphData → DSL string
|
|
3
|
+
*
|
|
4
|
+
* Pipeline:
|
|
5
|
+
* 1. Classify edges via EDGE_ARCHETYPE_MAP
|
|
6
|
+
* 2. Separate containment from operator edges
|
|
7
|
+
* 3. Group operator edges by source node
|
|
8
|
+
* 4. Sort lines by sortOrder
|
|
9
|
+
* 5. Merge same-operator same-verb targets
|
|
10
|
+
* 6. Serialize to indented DSL text
|
|
11
|
+
*
|
|
12
|
+
* @module notation/renderer
|
|
13
|
+
*/
|
|
14
|
+
import type { DescribeOptions, SubgraphData } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Render a subgraph as compact DSL notation.
|
|
17
|
+
*
|
|
18
|
+
* Example output:
|
|
19
|
+
* ```
|
|
20
|
+
* login {
|
|
21
|
+
* o- imports bcrypt
|
|
22
|
+
* > calls UserDB.findByEmail, createToken
|
|
23
|
+
* < reads config.auth
|
|
24
|
+
* => writes session
|
|
25
|
+
* >x throws AuthError
|
|
26
|
+
* ~>> emits 'auth:login'
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function renderNotation(input: SubgraphData, options?: DescribeOptions): string;
|
|
31
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/notation/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,eAAe,EAA+B,YAAY,EAAE,MAAM,YAAY,CAAC;AAK7F;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,eAAoB,GAC5B,MAAM,CAMR"}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notation Renderer — pure function: SubgraphData → DSL string
|
|
3
|
+
*
|
|
4
|
+
* Pipeline:
|
|
5
|
+
* 1. Classify edges via EDGE_ARCHETYPE_MAP
|
|
6
|
+
* 2. Separate containment from operator edges
|
|
7
|
+
* 3. Group operator edges by source node
|
|
8
|
+
* 4. Sort lines by sortOrder
|
|
9
|
+
* 5. Merge same-operator same-verb targets
|
|
10
|
+
* 6. Serialize to indented DSL text
|
|
11
|
+
*
|
|
12
|
+
* @module notation/renderer
|
|
13
|
+
*/
|
|
14
|
+
import { lookupEdge } from './archetypes.js';
|
|
15
|
+
import { getNodeDisplayName } from '../queries/NodeContext.js';
|
|
16
|
+
import { foldBlocks } from './fold.js';
|
|
17
|
+
/**
|
|
18
|
+
* Render a subgraph as compact DSL notation.
|
|
19
|
+
*
|
|
20
|
+
* Example output:
|
|
21
|
+
* ```
|
|
22
|
+
* login {
|
|
23
|
+
* o- imports bcrypt
|
|
24
|
+
* > calls UserDB.findByEmail, createToken
|
|
25
|
+
* < reads config.auth
|
|
26
|
+
* => writes session
|
|
27
|
+
* >x throws AuthError
|
|
28
|
+
* ~>> emits 'auth:login'
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function renderNotation(input, options = {}) {
|
|
33
|
+
const { depth = 1, archetypeFilter, budget = 7, includeLocations = false } = options;
|
|
34
|
+
const blocks = buildBlocks(input, depth, archetypeFilter, budget, includeLocations);
|
|
35
|
+
const finalBlocks = depth === 2 ? foldBlocks(blocks) : blocks;
|
|
36
|
+
return serializeBlocks(finalBlocks, 0);
|
|
37
|
+
}
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Block building
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
function buildBlocks(input, depth, archetypeFilter, budget, includeLocations) {
|
|
42
|
+
const { rootNodes, edges, nodeMap } = input;
|
|
43
|
+
// Index: src → edges, containment edges (src → child node IDs)
|
|
44
|
+
const outgoingBySource = new Map();
|
|
45
|
+
const childrenOf = new Map();
|
|
46
|
+
for (const edge of edges) {
|
|
47
|
+
const mapping = lookupEdge(edge.type);
|
|
48
|
+
if (mapping.archetype === 'contains') {
|
|
49
|
+
// Containment defines tree structure
|
|
50
|
+
if (!childrenOf.has(edge.src))
|
|
51
|
+
childrenOf.set(edge.src, []);
|
|
52
|
+
childrenOf.get(edge.src).push(edge.dst);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
if (!outgoingBySource.has(edge.src))
|
|
56
|
+
outgoingBySource.set(edge.src, []);
|
|
57
|
+
outgoingBySource.get(edge.src).push(edge);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Build set of node IDs that are descendants of LOOP nodes in containment tree
|
|
61
|
+
const insideLoopNodes = buildLoopDescendants(childrenOf, nodeMap);
|
|
62
|
+
const resolvedNames = resolveAnonymousNames(edges, nodeMap);
|
|
63
|
+
return rootNodes.map(node => buildBlock(node, outgoingBySource, childrenOf, nodeMap, depth, archetypeFilter, budget, includeLocations, insideLoopNodes, resolvedNames));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Collect all node IDs that are descendants of LOOP-type nodes in the containment tree.
|
|
67
|
+
* Uses BFS from each LOOP node, traversing containment children recursively.
|
|
68
|
+
*/
|
|
69
|
+
function buildLoopDescendants(childrenOf, nodeMap) {
|
|
70
|
+
const result = new Set();
|
|
71
|
+
// Find all LOOP nodes and collect their descendants
|
|
72
|
+
for (const [parentId, children] of childrenOf) {
|
|
73
|
+
const parentNode = nodeMap.get(parentId);
|
|
74
|
+
if (parentNode?.type === 'LOOP') {
|
|
75
|
+
// BFS to collect all descendants of this LOOP node
|
|
76
|
+
const queue = [...children];
|
|
77
|
+
while (queue.length > 0) {
|
|
78
|
+
const id = queue.shift();
|
|
79
|
+
if (result.has(id))
|
|
80
|
+
continue;
|
|
81
|
+
result.add(id);
|
|
82
|
+
const grandchildren = childrenOf.get(id);
|
|
83
|
+
if (grandchildren) {
|
|
84
|
+
queue.push(...grandchildren);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Resolve meaningful names for anonymous arrow functions and expressions.
|
|
93
|
+
*
|
|
94
|
+
* Priority:
|
|
95
|
+
* 1. Assignment: `const handler = () => {}` → "handler"
|
|
96
|
+
* 2. Callback: `setRequestHandler(Schema, λ)` → "λ → setRequestHandler(Schema)"
|
|
97
|
+
* 3. Fallback: "λ"
|
|
98
|
+
*/
|
|
99
|
+
function resolveAnonymousNames(edges, nodeMap) {
|
|
100
|
+
const resolved = new Map();
|
|
101
|
+
// Reverse index: dstId → edges (for ASSIGNED_FROM and PASSES_ARGUMENT)
|
|
102
|
+
const incomingByDst = new Map();
|
|
103
|
+
// Forward index: srcId → PASSES_ARGUMENT edges (for finding siblings)
|
|
104
|
+
const passArgBySrc = new Map();
|
|
105
|
+
for (const edge of edges) {
|
|
106
|
+
if (edge.type === 'ASSIGNED_FROM' || edge.type === 'PASSES_ARGUMENT') {
|
|
107
|
+
if (!incomingByDst.has(edge.dst))
|
|
108
|
+
incomingByDst.set(edge.dst, []);
|
|
109
|
+
incomingByDst.get(edge.dst).push(edge);
|
|
110
|
+
}
|
|
111
|
+
if (edge.type === 'PASSES_ARGUMENT') {
|
|
112
|
+
if (!passArgBySrc.has(edge.src))
|
|
113
|
+
passArgBySrc.set(edge.src, []);
|
|
114
|
+
passArgBySrc.get(edge.src).push(edge);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
for (const [nodeId, node] of nodeMap) {
|
|
118
|
+
if (node.name !== '<arrow>' && node.name !== '<expression>')
|
|
119
|
+
continue;
|
|
120
|
+
const incoming = incomingByDst.get(nodeId) ?? [];
|
|
121
|
+
// Priority 1: Assignment — const handler = () => {}
|
|
122
|
+
const assignEdge = incoming.find(e => e.type === 'ASSIGNED_FROM');
|
|
123
|
+
if (assignEdge) {
|
|
124
|
+
const srcNode = nodeMap.get(assignEdge.src);
|
|
125
|
+
if (srcNode?.name && srcNode.name !== '<arrow>' && srcNode.name !== '<expression>') {
|
|
126
|
+
resolved.set(nodeId, srcNode.name);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Priority 2: Callback — setRequestHandler(Schema, λ)
|
|
131
|
+
const passEdge = incoming.find(e => e.type === 'PASSES_ARGUMENT');
|
|
132
|
+
if (passEdge) {
|
|
133
|
+
const callNode = nodeMap.get(passEdge.src);
|
|
134
|
+
const callName = callNode ? getNodeDisplayName(callNode) : null;
|
|
135
|
+
if (callName && callName !== '<arrow>' && callName !== '<expression>' && callName !== 'λ') {
|
|
136
|
+
// Named sibling args (skip other anonymous ones)
|
|
137
|
+
const allSiblings = passArgBySrc.get(passEdge.src) ?? [];
|
|
138
|
+
const namedSiblings = allSiblings
|
|
139
|
+
.filter(e => e.dst !== nodeId)
|
|
140
|
+
.map(e => {
|
|
141
|
+
const argNode = nodeMap.get(e.dst);
|
|
142
|
+
if (!argNode?.name)
|
|
143
|
+
return null;
|
|
144
|
+
if (argNode.name === '<arrow>' || argNode.name === '<expression>')
|
|
145
|
+
return null;
|
|
146
|
+
return argNode.name;
|
|
147
|
+
})
|
|
148
|
+
.filter((n) => n !== null);
|
|
149
|
+
// Multiple lambdas in same call → add index to distinguish
|
|
150
|
+
const lambdaCount = allSiblings.filter(e => {
|
|
151
|
+
const n = nodeMap.get(e.dst);
|
|
152
|
+
return n && (n.name === '<arrow>' || n.name === '<expression>');
|
|
153
|
+
}).length;
|
|
154
|
+
const indexSuffix = lambdaCount > 1
|
|
155
|
+
? String(passEdge.metadata?.index ?? passEdge.metadata?.argIndex ?? '')
|
|
156
|
+
: '';
|
|
157
|
+
const argStr = namedSiblings.length > 0 ? `(${namedSiblings.join(', ')})` : '';
|
|
158
|
+
resolved.set(nodeId, `λ${indexSuffix} → ${callName}${argStr}`);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Priority 3: Fallback
|
|
163
|
+
resolved.set(nodeId, 'λ');
|
|
164
|
+
}
|
|
165
|
+
return resolved;
|
|
166
|
+
}
|
|
167
|
+
function buildBlock(node, outgoingBySource, childrenOf, nodeMap, depth, archetypeFilter, budget, includeLocations, insideLoopNodes, resolvedNames) {
|
|
168
|
+
const displayName = resolvedNames.get(node.id) ?? getNodeDisplayName(node);
|
|
169
|
+
const location = includeLocations && node.file
|
|
170
|
+
? `${node.file}${node.line ? ':' + node.line : ''}`
|
|
171
|
+
: undefined;
|
|
172
|
+
// LOD 0: names only — no edges, no children
|
|
173
|
+
if (depth <= 0) {
|
|
174
|
+
return { nodeId: node.id, displayName, nodeType: node.type, lines: [], children: [], location };
|
|
175
|
+
}
|
|
176
|
+
// LOD 1+: build edge lines
|
|
177
|
+
const nodeEdges = outgoingBySource.get(node.id) ?? [];
|
|
178
|
+
const lines = buildLines(nodeEdges, nodeMap, archetypeFilter, budget, resolvedNames);
|
|
179
|
+
// Apply [] loop modifier if this node is inside a LOOP
|
|
180
|
+
// Combines with existing modifiers: [] ?? > calls foo
|
|
181
|
+
if (insideLoopNodes.has(node.id)) {
|
|
182
|
+
for (const line of lines) {
|
|
183
|
+
line.modifier = line.modifier ? `[] ${line.modifier}` : '[]';
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// LOD 2+: recurse into contained children
|
|
187
|
+
let children = [];
|
|
188
|
+
if (depth >= 2) {
|
|
189
|
+
const childIds = childrenOf.get(node.id) ?? [];
|
|
190
|
+
children = childIds
|
|
191
|
+
.map(id => nodeMap.get(id))
|
|
192
|
+
.filter((n) => n != null)
|
|
193
|
+
.map(child => buildBlock(child, outgoingBySource, childrenOf, nodeMap, depth - 1, archetypeFilter, budget, includeLocations, insideLoopNodes, resolvedNames));
|
|
194
|
+
}
|
|
195
|
+
return { nodeId: node.id, displayName, nodeType: node.type, lines, children, location };
|
|
196
|
+
}
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
// Line building — group, sort, merge
|
|
199
|
+
// ---------------------------------------------------------------------------
|
|
200
|
+
function buildLines(edges, nodeMap, archetypeFilter, budget, resolvedNames) {
|
|
201
|
+
// Group by modifier+operator+verb key (modifier separates certain from uncertain)
|
|
202
|
+
const groups = new Map();
|
|
203
|
+
for (const edge of edges) {
|
|
204
|
+
const mapping = lookupEdge(edge.type);
|
|
205
|
+
// Apply archetype filter
|
|
206
|
+
if (archetypeFilter && !archetypeFilter.includes(mapping.archetype))
|
|
207
|
+
continue;
|
|
208
|
+
const targetNode = nodeMap.get(edge.dst);
|
|
209
|
+
const targetName = resolvedNames.get(edge.dst) ?? (targetNode ? getNodeDisplayName(targetNode) : edge.dst);
|
|
210
|
+
// Detect dynamic/uncertain edges
|
|
211
|
+
const modifier = isDynamicEdge(edge) ? '??' : undefined;
|
|
212
|
+
const key = `${modifier ?? ''}|${mapping.operator}|${mapping.verb}`;
|
|
213
|
+
if (!groups.has(key)) {
|
|
214
|
+
groups.set(key, {
|
|
215
|
+
operator: mapping.operator,
|
|
216
|
+
verb: mapping.verb,
|
|
217
|
+
targets: [],
|
|
218
|
+
sortOrder: mapping.sortOrder,
|
|
219
|
+
modifier,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
groups.get(key).targets.push(targetName);
|
|
223
|
+
}
|
|
224
|
+
// Sort by sortOrder
|
|
225
|
+
const sorted = Array.from(groups.values()).sort((a, b) => a.sortOrder - b.sortOrder);
|
|
226
|
+
// Apply budget: show top-N, summarize rest
|
|
227
|
+
if (sorted.length > budget) {
|
|
228
|
+
const shown = sorted.slice(0, budget);
|
|
229
|
+
const hidden = sorted.slice(budget);
|
|
230
|
+
const hiddenCount = hidden.reduce((sum, g) => sum + g.targets.length, 0);
|
|
231
|
+
shown.push({
|
|
232
|
+
operator: '',
|
|
233
|
+
verb: `...+${hiddenCount} more`,
|
|
234
|
+
targets: [],
|
|
235
|
+
sortOrder: 999,
|
|
236
|
+
});
|
|
237
|
+
return shown.map(g => ({
|
|
238
|
+
operator: g.operator,
|
|
239
|
+
verb: g.verb,
|
|
240
|
+
targets: g.targets,
|
|
241
|
+
sortOrder: g.sortOrder,
|
|
242
|
+
modifier: g.modifier,
|
|
243
|
+
}));
|
|
244
|
+
}
|
|
245
|
+
return sorted.map(g => ({
|
|
246
|
+
operator: g.operator,
|
|
247
|
+
verb: g.verb,
|
|
248
|
+
targets: g.targets,
|
|
249
|
+
sortOrder: g.sortOrder,
|
|
250
|
+
modifier: g.modifier,
|
|
251
|
+
}));
|
|
252
|
+
}
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
// Edge metadata helpers
|
|
255
|
+
// ---------------------------------------------------------------------------
|
|
256
|
+
/**
|
|
257
|
+
* Check if an edge is dynamic/uncertain based on its metadata.
|
|
258
|
+
*
|
|
259
|
+
* An edge is dynamic/uncertain if any of these hold:
|
|
260
|
+
* - metadata.resolved === false (unresolved reference)
|
|
261
|
+
* - metadata.confidence exists and is < 1.0 (low-confidence inference)
|
|
262
|
+
* - metadata.dynamic === true (dynamic dispatch)
|
|
263
|
+
*/
|
|
264
|
+
function isDynamicEdge(edge) {
|
|
265
|
+
const meta = edge.metadata;
|
|
266
|
+
if (!meta)
|
|
267
|
+
return false;
|
|
268
|
+
if (meta.resolved === false)
|
|
269
|
+
return true;
|
|
270
|
+
if (typeof meta.confidence === 'number' && meta.confidence < 1.0)
|
|
271
|
+
return true;
|
|
272
|
+
if (meta.dynamic === true)
|
|
273
|
+
return true;
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
// Serialization
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
function serializeBlocks(blocks, indentLevel) {
|
|
280
|
+
return blocks.map(block => serializeBlock(block, indentLevel)).join('\n');
|
|
281
|
+
}
|
|
282
|
+
function serializeBlock(block, indentLevel) {
|
|
283
|
+
const indent = ' '.repeat(indentLevel);
|
|
284
|
+
const hasContent = block.lines.length > 0 || block.children.length > 0;
|
|
285
|
+
// Header
|
|
286
|
+
const loc = block.location ? ` (${block.location})` : '';
|
|
287
|
+
let result;
|
|
288
|
+
if (!hasContent) {
|
|
289
|
+
// Leaf node — just name
|
|
290
|
+
result = `${indent}${block.displayName}${loc}`;
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
result = `${indent}${block.displayName}${loc} {\n`;
|
|
294
|
+
// Lines
|
|
295
|
+
for (const line of block.lines) {
|
|
296
|
+
result += serializeLine(line, indentLevel + 1);
|
|
297
|
+
}
|
|
298
|
+
// Children
|
|
299
|
+
if (block.children.length > 0) {
|
|
300
|
+
result += serializeBlocks(block.children, indentLevel + 1) + '\n';
|
|
301
|
+
}
|
|
302
|
+
result += `${indent}}`;
|
|
303
|
+
}
|
|
304
|
+
return result;
|
|
305
|
+
}
|
|
306
|
+
function serializeLine(line, indentLevel) {
|
|
307
|
+
const indent = ' '.repeat(indentLevel);
|
|
308
|
+
const mod = line.modifier ? `${line.modifier} ` : '';
|
|
309
|
+
const prefix = line.operator ? `${line.operator} ` : '';
|
|
310
|
+
if (line.targets.length === 0) {
|
|
311
|
+
return `${indent}${mod}${prefix}${line.verb}\n`;
|
|
312
|
+
}
|
|
313
|
+
return `${indent}${mod}${prefix}${line.verb} ${line.targets.join(', ')}\n`;
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=renderer.js.map
|