@flanksource/clicky-ui 0.3.44 → 0.3.45
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/README.md +2 -0
- package/dist/ai.cjs +4 -2
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +3 -1
- package/dist/components/MdxEditorField.cjs +40 -22
- package/dist/components/MdxEditorField.cjs.map +1 -1
- package/dist/components/MdxEditorField.d.ts.map +1 -1
- package/dist/components/MdxEditorField.js +41 -23
- package/dist/components/MdxEditorField.js.map +1 -1
- package/dist/components/json-schema-form-item-summary.cjs +6 -1
- package/dist/components/json-schema-form-item-summary.cjs.map +1 -1
- package/dist/components/json-schema-form-item-summary.d.ts.map +1 -1
- package/dist/components/json-schema-form-item-summary.js +6 -1
- package/dist/components/json-schema-form-item-summary.js.map +1 -1
- package/dist/data/CodeBlock.cjs +3 -2
- package/dist/data/CodeBlock.cjs.map +1 -1
- package/dist/data/CodeBlock.d.ts +3 -1
- package/dist/data/CodeBlock.d.ts.map +1 -1
- package/dist/data/CodeBlock.js +3 -2
- package/dist/data/CodeBlock.js.map +1 -1
- package/dist/data/GraphDiagram.cjs +18 -6
- package/dist/data/GraphDiagram.cjs.map +1 -1
- package/dist/data/GraphDiagram.d.ts +9 -1
- package/dist/data/GraphDiagram.d.ts.map +1 -1
- package/dist/data/GraphDiagram.js +18 -6
- package/dist/data/GraphDiagram.js.map +1 -1
- package/dist/data/GraphDiagramNodes.cjs +38 -29
- package/dist/data/GraphDiagramNodes.cjs.map +1 -1
- package/dist/data/GraphDiagramNodes.d.ts +8 -2
- package/dist/data/GraphDiagramNodes.d.ts.map +1 -1
- package/dist/data/GraphDiagramNodes.js +38 -29
- package/dist/data/GraphDiagramNodes.js.map +1 -1
- package/dist/data/JsonView.cjs +118 -49
- package/dist/data/JsonView.cjs.map +1 -1
- package/dist/data/JsonView.d.ts +13 -10
- package/dist/data/JsonView.d.ts.map +1 -1
- package/dist/data/JsonView.js +118 -49
- package/dist/data/JsonView.js.map +1 -1
- package/dist/data/MarkdownEditor.cjs +2 -2
- package/dist/data/MarkdownEditor.cjs.map +1 -1
- package/dist/data/MarkdownEditor.js +2 -2
- package/dist/data/MarkdownEditor.js.map +1 -1
- package/dist/data/ai/AdvancedChatConfig.cjs +90 -249
- package/dist/data/ai/AdvancedChatConfig.cjs.map +1 -1
- package/dist/data/ai/AdvancedChatConfig.d.ts +2 -5
- package/dist/data/ai/AdvancedChatConfig.d.ts.map +1 -1
- package/dist/data/ai/AdvancedChatConfig.js +91 -250
- package/dist/data/ai/AdvancedChatConfig.js.map +1 -1
- package/dist/data/ai/ChatButton.cjs +2 -0
- package/dist/data/ai/ChatButton.cjs.map +1 -1
- package/dist/data/ai/ChatButton.d.ts +1 -1
- package/dist/data/ai/ChatButton.d.ts.map +1 -1
- package/dist/data/ai/ChatButton.js +2 -0
- package/dist/data/ai/ChatButton.js.map +1 -1
- package/dist/data/ai/ChatFab.cjs +5 -1
- package/dist/data/ai/ChatFab.cjs.map +1 -1
- package/dist/data/ai/ChatFab.d.ts +5 -1
- package/dist/data/ai/ChatFab.d.ts.map +1 -1
- package/dist/data/ai/ChatFab.js +5 -1
- package/dist/data/ai/ChatFab.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +2 -8
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.js +2 -8
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/ChatWindow.runtime.cjs +0 -5
- package/dist/data/ai/ChatWindow.runtime.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.runtime.d.ts +0 -2
- package/dist/data/ai/ChatWindow.runtime.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.runtime.js +0 -5
- package/dist/data/ai/ChatWindow.runtime.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs +2 -2
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.js +2 -2
- package/dist/data/ai/PromptRunEditor/runtimeActions.js.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.cjs +3 -6
- package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.js +3 -6
- package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
- package/dist/data/ai/SessionViewer.cjs +13 -4
- package/dist/data/ai/SessionViewer.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.d.ts +5 -1
- package/dist/data/ai/SessionViewer.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.header.cjs +1 -1
- package/dist/data/ai/SessionViewer.header.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.header.js +1 -1
- package/dist/data/ai/SessionViewer.header.js.map +1 -1
- package/dist/data/ai/SessionViewer.js +13 -4
- package/dist/data/ai/SessionViewer.js.map +1 -1
- package/dist/data/ai/SessionViewer.model.cjs +2 -0
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +1 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js +2 -0
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.rows.cjs +41 -27
- package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.rows.d.ts +4 -2
- package/dist/data/ai/SessionViewer.rows.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.rows.js +41 -27
- package/dist/data/ai/SessionViewer.rows.js.map +1 -1
- package/dist/data/ai/SessionViewer.tokens.cjs +35 -0
- package/dist/data/ai/SessionViewer.tokens.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.tokens.d.ts +5 -0
- package/dist/data/ai/SessionViewer.tokens.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.tokens.js +35 -0
- package/dist/data/ai/SessionViewer.tokens.js.map +1 -0
- package/dist/data/ai/SessionViewer.tool-cost.cjs +128 -0
- package/dist/data/ai/SessionViewer.tool-cost.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.tool-cost.d.ts +6 -0
- package/dist/data/ai/SessionViewer.tool-cost.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.tool-cost.js +128 -0
- package/dist/data/ai/SessionViewer.tool-cost.js.map +1 -0
- package/dist/data/ai/SessionViewer.tool-details.cjs +3 -1
- package/dist/data/ai/SessionViewer.tool-details.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.tool-details.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.tool-details.js +3 -1
- package/dist/data/ai/SessionViewer.tool-details.js.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.cjs +55 -35
- package/dist/data/ai/SessionViewer.tool-row.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.d.ts +2 -1
- package/dist/data/ai/SessionViewer.tool-row.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.js +55 -35
- package/dist/data/ai/SessionViewer.tool-row.js.map +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +4 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.cjs +18 -1
- package/dist/data/ai/SessionViewerMenu.cjs.map +1 -1
- package/dist/data/ai/SessionViewerMenu.d.ts +6 -1
- package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.js +18 -1
- package/dist/data/ai/SessionViewerMenu.js.map +1 -1
- package/dist/data/ai/ToolPreferences.cjs +149 -143
- package/dist/data/ai/ToolPreferences.cjs.map +1 -1
- package/dist/data/ai/ToolPreferences.d.ts +20 -6
- package/dist/data/ai/ToolPreferences.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferences.js +151 -146
- package/dist/data/ai/ToolPreferences.js.map +1 -1
- package/dist/data/ai/ToolPreferences.model.cjs +14 -10
- package/dist/data/ai/ToolPreferences.model.cjs.map +1 -1
- package/dist/data/ai/ToolPreferences.model.d.ts +1 -0
- package/dist/data/ai/ToolPreferences.model.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferences.model.js +15 -11
- package/dist/data/ai/ToolPreferences.model.js.map +1 -1
- package/dist/data/ai/ToolPreferencesList.cjs +1 -0
- package/dist/data/ai/ToolPreferencesList.cjs.map +1 -1
- package/dist/data/ai/ToolPreferencesList.d.ts +4 -1
- package/dist/data/ai/ToolPreferencesList.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferencesList.js +2 -1
- package/dist/data/ai/ToolPreferencesList.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.cjs +52 -53
- package/dist/data/ai/ToolSchemaBrowser.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.d.ts +6 -3
- package/dist/data/ai/ToolSchemaBrowser.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.directory-header.cjs +9 -13
- package/dist/data/ai/ToolSchemaBrowser.directory-header.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.directory-header.d.ts +5 -2
- package/dist/data/ai/ToolSchemaBrowser.directory-header.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.directory-header.js +9 -13
- package/dist/data/ai/ToolSchemaBrowser.directory-header.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.js +53 -54
- package/dist/data/ai/ToolSchemaBrowser.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.model.cjs +19 -27
- package/dist/data/ai/ToolSchemaBrowser.model.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.model.d.ts +9 -6
- package/dist/data/ai/ToolSchemaBrowser.model.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.model.js +20 -28
- package/dist/data/ai/ToolSchemaBrowser.model.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.sidebar.cjs +12 -213
- package/dist/data/ai/ToolSchemaBrowser.sidebar.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.sidebar.d.ts +1 -3
- package/dist/data/ai/ToolSchemaBrowser.sidebar.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.sidebar.js +13 -214
- package/dist/data/ai/ToolSchemaBrowser.sidebar.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.strategies.cjs +54 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.cjs.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.d.ts +9 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.d.ts.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.js +54 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.js.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.cjs +179 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.cjs.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.d.ts +20 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.d.ts.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.js +179 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.js.map +1 -0
- package/dist/data/ai/index.d.ts +2 -2
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs +8 -28
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs.map +1 -1
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.d.ts.map +1 -1
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js +9 -29
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js.map +1 -1
- package/dist/data/ai/session-token-sizing.d.ts +32 -0
- package/dist/data/ai/session-token-sizing.d.ts.map +1 -0
- package/dist/data/ai/use-session-token-sizing.cjs +73 -0
- package/dist/data/ai/use-session-token-sizing.cjs.map +1 -0
- package/dist/data/ai/use-session-token-sizing.d.ts +21 -0
- package/dist/data/ai/use-session-token-sizing.d.ts.map +1 -0
- package/dist/data/ai/use-session-token-sizing.js +73 -0
- package/dist/data/ai/use-session-token-sizing.js.map +1 -0
- package/dist/data/call-graph/CallGraph.cjs +250 -0
- package/dist/data/call-graph/CallGraph.cjs.map +1 -0
- package/dist/data/call-graph/CallGraph.d.ts +69 -0
- package/dist/data/call-graph/CallGraph.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraph.js +250 -0
- package/dist/data/call-graph/CallGraph.js.map +1 -0
- package/dist/data/call-graph/CallGraphGlyphs.cjs +39 -0
- package/dist/data/call-graph/CallGraphGlyphs.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphGlyphs.d.ts +19 -0
- package/dist/data/call-graph/CallGraphGlyphs.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphGlyphs.js +39 -0
- package/dist/data/call-graph/CallGraphGlyphs.js.map +1 -0
- package/dist/data/call-graph/CallGraphMembers.cjs +50 -0
- package/dist/data/call-graph/CallGraphMembers.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphMembers.d.ts +22 -0
- package/dist/data/call-graph/CallGraphMembers.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphMembers.js +50 -0
- package/dist/data/call-graph/CallGraphMembers.js.map +1 -0
- package/dist/data/call-graph/CallGraphParts.cjs +204 -0
- package/dist/data/call-graph/CallGraphParts.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphParts.d.ts +44 -0
- package/dist/data/call-graph/CallGraphParts.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphParts.js +204 -0
- package/dist/data/call-graph/CallGraphParts.js.map +1 -0
- package/dist/data/call-graph/CallGraphToolbar.cjs +186 -0
- package/dist/data/call-graph/CallGraphToolbar.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphToolbar.d.ts +45 -0
- package/dist/data/call-graph/CallGraphToolbar.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphToolbar.js +186 -0
- package/dist/data/call-graph/CallGraphToolbar.js.map +1 -0
- package/dist/data/call-graph/call-graph-exclude.cjs +75 -0
- package/dist/data/call-graph/call-graph-exclude.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-exclude.d.ts +31 -0
- package/dist/data/call-graph/call-graph-exclude.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-exclude.js +75 -0
- package/dist/data/call-graph/call-graph-exclude.js.map +1 -0
- package/dist/data/call-graph/call-graph-labels.cjs +96 -0
- package/dist/data/call-graph/call-graph-labels.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-labels.d.ts +53 -0
- package/dist/data/call-graph/call-graph-labels.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-labels.js +96 -0
- package/dist/data/call-graph/call-graph-labels.js.map +1 -0
- package/dist/data/call-graph/call-graph-model.cjs +161 -0
- package/dist/data/call-graph/call-graph-model.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-model.d.ts +102 -0
- package/dist/data/call-graph/call-graph-model.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-model.js +161 -0
- package/dist/data/call-graph/call-graph-model.js.map +1 -0
- package/dist/data/call-graph/call-graph-vocabulary.cjs +177 -0
- package/dist/data/call-graph/call-graph-vocabulary.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-vocabulary.d.ts +72 -0
- package/dist/data/call-graph/call-graph-vocabulary.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-vocabulary.js +177 -0
- package/dist/data/call-graph/call-graph-vocabulary.js.map +1 -0
- package/dist/data/call-graph/call-graph.fixtures.d.ts +63 -0
- package/dist/data/call-graph/call-graph.fixtures.d.ts.map +1 -0
- package/dist/data/call-graph/index.d.ts +7 -0
- package/dist/data/call-graph/index.d.ts.map +1 -0
- package/dist/data/call-graph/types.cjs +5 -0
- package/dist/data/call-graph/types.cjs.map +1 -0
- package/dist/data/call-graph/types.d.ts +135 -0
- package/dist/data/call-graph/types.d.ts.map +1 -0
- package/dist/data/call-graph/types.js +5 -0
- package/dist/data/call-graph/types.js.map +1 -0
- package/dist/data/call-graph/use-call-graph.cjs +93 -0
- package/dist/data/call-graph/use-call-graph.cjs.map +1 -0
- package/dist/data/call-graph/use-call-graph.d.ts +24 -0
- package/dist/data/call-graph/use-call-graph.d.ts.map +1 -0
- package/dist/data/call-graph/use-call-graph.js +93 -0
- package/dist/data/call-graph/use-call-graph.js.map +1 -0
- package/dist/data/chat/Chat.cjs +39 -15
- package/dist/data/chat/Chat.cjs.map +1 -1
- package/dist/data/chat/Chat.d.ts.map +1 -1
- package/dist/data/chat/Chat.fixtures.cjs +2 -2
- package/dist/data/chat/Chat.fixtures.cjs.map +1 -1
- package/dist/data/chat/Chat.fixtures.js +2 -2
- package/dist/data/chat/Chat.fixtures.js.map +1 -1
- package/dist/data/chat/Chat.js +40 -16
- package/dist/data/chat/Chat.js.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.cjs +3 -6
- package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.js +3 -6
- package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
- package/dist/data/chat/ContextMeter.bar.cjs +5 -8
- package/dist/data/chat/ContextMeter.bar.cjs.map +1 -1
- package/dist/data/chat/ContextMeter.bar.d.ts +1 -1
- package/dist/data/chat/ContextMeter.bar.d.ts.map +1 -1
- package/dist/data/chat/ContextMeter.bar.js +5 -8
- package/dist/data/chat/ContextMeter.bar.js.map +1 -1
- package/dist/data/chat/ContextMeter.cjs +18 -19
- package/dist/data/chat/ContextMeter.cjs.map +1 -1
- package/dist/data/chat/ContextMeter.d.ts +1 -1
- package/dist/data/chat/ContextMeter.d.ts.map +1 -1
- package/dist/data/chat/ContextMeter.js +18 -19
- package/dist/data/chat/ContextMeter.js.map +1 -1
- package/dist/data/chat/Conversation.cjs +2 -1
- package/dist/data/chat/Conversation.cjs.map +1 -1
- package/dist/data/chat/Conversation.d.ts +4 -1
- package/dist/data/chat/Conversation.d.ts.map +1 -1
- package/dist/data/chat/Conversation.js +2 -1
- package/dist/data/chat/Conversation.js.map +1 -1
- package/dist/data/chat/Message.cjs +39 -12
- package/dist/data/chat/Message.cjs.map +1 -1
- package/dist/data/chat/Message.d.ts +1 -1
- package/dist/data/chat/Message.d.ts.map +1 -1
- package/dist/data/chat/Message.js +40 -13
- package/dist/data/chat/Message.js.map +1 -1
- package/dist/data/chat/ToolCall.cjs +60 -5
- package/dist/data/chat/ToolCall.cjs.map +1 -1
- package/dist/data/chat/ToolCall.d.ts +7 -2
- package/dist/data/chat/ToolCall.d.ts.map +1 -1
- package/dist/data/chat/ToolCall.js +60 -5
- package/dist/data/chat/ToolCall.js.map +1 -1
- package/dist/data/chat/approval.cjs.map +1 -1
- package/dist/data/chat/approval.d.ts +2 -2
- package/dist/data/chat/approval.d.ts.map +1 -1
- package/dist/data/chat/approval.js.map +1 -1
- package/dist/data/chat/tool-policy.cjs +59 -2
- package/dist/data/chat/tool-policy.cjs.map +1 -1
- package/dist/data/chat/tool-policy.d.ts +9 -0
- package/dist/data/chat/tool-policy.d.ts.map +1 -1
- package/dist/data/chat/tool-policy.js +59 -2
- package/dist/data/chat/tool-policy.js.map +1 -1
- package/dist/data/chat/types.cjs +6 -0
- package/dist/data/chat/types.cjs.map +1 -1
- package/dist/data/chat/types.d.ts +13 -4
- package/dist/data/chat/types.d.ts.map +1 -1
- package/dist/data/chat/types.js +7 -1
- package/dist/data/chat/types.js.map +1 -1
- package/dist/data/chat/usage-snapshot.cjs +11 -6
- package/dist/data/chat/usage-snapshot.cjs.map +1 -1
- package/dist/data/chat/usage-snapshot.d.ts +0 -1
- package/dist/data/chat/usage-snapshot.d.ts.map +1 -1
- package/dist/data/chat/usage-snapshot.js +11 -6
- package/dist/data/chat/usage-snapshot.js.map +1 -1
- package/dist/data/diagnostics/StackFrameRow.cjs +3 -3
- package/dist/data/diagnostics/StackFrameRow.cjs.map +1 -1
- package/dist/data/diagnostics/StackFrameRow.js +3 -3
- package/dist/data/diagnostics/StackFrameRow.js.map +1 -1
- package/dist/data/graph-columns-layout.cjs +26 -10
- package/dist/data/graph-columns-layout.cjs.map +1 -1
- package/dist/data/graph-columns-layout.d.ts +8 -0
- package/dist/data/graph-columns-layout.d.ts.map +1 -1
- package/dist/data/graph-columns-layout.js +26 -10
- package/dist/data/graph-columns-layout.js.map +1 -1
- package/dist/data/graph-diagram-model.cjs.map +1 -1
- package/dist/data/graph-diagram-model.d.ts +5 -0
- package/dist/data/graph-diagram-model.d.ts.map +1 -1
- package/dist/data/graph-diagram-model.js.map +1 -1
- package/dist/data/graph-edge-routing.cjs +9 -3
- package/dist/data/graph-edge-routing.cjs.map +1 -1
- package/dist/data/graph-edge-routing.d.ts +2 -0
- package/dist/data/graph-edge-routing.d.ts.map +1 -1
- package/dist/data/graph-edge-routing.js +9 -3
- package/dist/data/graph-edge-routing.js.map +1 -1
- package/dist/data/json-view/JsonSource.cjs +84 -0
- package/dist/data/json-view/JsonSource.cjs.map +1 -0
- package/dist/data/json-view/JsonSource.d.ts +7 -0
- package/dist/data/json-view/JsonSource.d.ts.map +1 -0
- package/dist/data/json-view/JsonSource.js +84 -0
- package/dist/data/json-view/JsonSource.js.map +1 -0
- package/dist/data/json-view/parse-prefix.cjs +132 -0
- package/dist/data/json-view/parse-prefix.cjs.map +1 -0
- package/dist/data/json-view/parse-prefix.d.ts +11 -0
- package/dist/data/json-view/parse-prefix.d.ts.map +1 -0
- package/dist/data/json-view/parse-prefix.js +132 -0
- package/dist/data/json-view/parse-prefix.js.map +1 -0
- package/dist/data/json-view/parse-source.cjs +62 -0
- package/dist/data/json-view/parse-source.cjs.map +1 -0
- package/dist/data/json-view/parse-source.d.ts +16 -0
- package/dist/data/json-view/parse-source.d.ts.map +1 -0
- package/dist/data/json-view/parse-source.js +62 -0
- package/dist/data/json-view/parse-source.js.map +1 -0
- package/dist/data/json-view/story-fixtures.d.ts +6 -0
- package/dist/data/json-view/story-fixtures.d.ts.map +1 -0
- package/dist/data/json-view/types.d.ts +14 -0
- package/dist/data/json-view/types.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBar.cjs +2 -5
- package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.d.ts +2 -4
- package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.fields.cjs +2 -2
- package/dist/data/runtime/RuntimeBar.fields.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.fields.js +2 -2
- package/dist/data/runtime/RuntimeBar.fields.js.map +1 -1
- package/dist/data/runtime/RuntimeBar.js +2 -5
- package/dist/data/runtime/RuntimeBar.js.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.cjs +4 -1
- package/dist/data/runtime/RuntimeBar.selection.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.js +5 -2
- package/dist/data/runtime/RuntimeBar.selection.js.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.cjs +1 -5
- package/dist/data/runtime/RuntimeBarActions.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts +1 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.js +1 -5
- package/dist/data/runtime/RuntimeBarActions.js.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.cjs +6 -14
- package/dist/data/runtime/RuntimeBarIdentity.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.d.ts +0 -1
- package/dist/data/runtime/RuntimeBarIdentity.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.js +6 -14
- package/dist/data/runtime/RuntimeBarIdentity.js.map +1 -1
- package/dist/data/runtime/RuntimeBarLayout.cjs +8 -27
- package/dist/data/runtime/RuntimeBarLayout.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarLayout.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarLayout.js +8 -27
- package/dist/data/runtime/RuntimeBarLayout.js.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.cjs +1 -5
- package/dist/data/runtime/RuntimeBarSegment.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.js +1 -5
- package/dist/data/runtime/RuntimeBarSegment.js.map +1 -1
- package/dist/data/runtime/use-runtime-bar-overflow.cjs +4 -10
- package/dist/data/runtime/use-runtime-bar-overflow.cjs.map +1 -1
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts +1 -2
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts.map +1 -1
- package/dist/data/runtime/use-runtime-bar-overflow.js +4 -10
- package/dist/data/runtime/use-runtime-bar-overflow.js.map +1 -1
- package/dist/data/test-runner/TestRunner.fixtures.d.ts +0 -20
- package/dist/data/test-runner/TestRunner.fixtures.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.large-fixtures.d.ts +22 -0
- package/dist/data/test-runner/TestRunner.large-fixtures.d.ts.map +1 -0
- package/dist/data/use-pan-zoom.cjs +23 -10
- package/dist/data/use-pan-zoom.cjs.map +1 -1
- package/dist/data/use-pan-zoom.d.ts +16 -2
- package/dist/data/use-pan-zoom.d.ts.map +1 -1
- package/dist/data/use-pan-zoom.js +23 -10
- package/dist/data/use-pan-zoom.js.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +26 -2
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +1 -0
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +24 -0
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +28 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/layout/Workspace.cjs +13 -4
- package/dist/layout/Workspace.cjs.map +1 -1
- package/dist/layout/Workspace.d.ts +7 -2
- package/dist/layout/Workspace.d.ts.map +1 -1
- package/dist/layout/Workspace.js +13 -4
- package/dist/layout/Workspace.js.map +1 -1
- package/dist/lib/permission-strategies.cjs +71 -11
- package/dist/lib/permission-strategies.cjs.map +1 -1
- package/dist/lib/permission-strategies.d.ts +3 -0
- package/dist/lib/permission-strategies.d.ts.map +1 -1
- package/dist/lib/permission-strategies.js +71 -11
- package/dist/lib/permission-strategies.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +5 -3
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.cjs +0 -57
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.cjs.map +0 -1
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.d.ts +0 -7
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.d.ts.map +0 -1
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.js +0 -57
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.js.map +0 -1
- package/dist/data/runtime/RuntimeBar.context.cjs +0 -8
- package/dist/data/runtime/RuntimeBar.context.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBar.context.d.ts +0 -2
- package/dist/data/runtime/RuntimeBar.context.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBar.context.js +0 -8
- package/dist/data/runtime/RuntimeBar.context.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-graph-model.cjs","sources":["../../../src/data/call-graph/call-graph-model.ts"],"sourcesContent":["// Pure mapping from a call graph to what GraphDiagram draws, and how a `+N` expansion merges into the\n// held graph. It decides what is shown and leaves drawing a glyph to the DiagramGlyphs it is handed,\n// so it renders nothing itself.\nimport type { ReactNode } from \"react\";\nimport type { BadgeTone } from \"../Badge\";\nimport type { GraphDiagramEdge, GraphDiagramGroup, GraphDiagramNode } from \"../graph-diagram-model\";\nimport { edgeLabel, edgeTitle, groupCaption, isConditional, type PillOptions } from \"./call-graph-labels\";\nimport { nodeTitle, siteKey, type CallGraphVocabulary } from \"./call-graph-vocabulary\";\nimport {\n CALL_GRAPH_ACCESS,\n type CallGraph,\n type CallGraphAccess,\n type CallGraphDirection,\n type CallGraphEdge,\n type CallGraphEdgeLabels,\n type CallGraphEdgeType,\n type CallGraphGroup,\n type CallGraphNode,\n type CallGraphSite,\n} from \"./types\";\n\n/** The deepest graph uir builds (graph.MaxDepth). */\nexport const CALL_GRAPH_MAX_DEPTH = 8;\n/** The depth uir builds when none is asked for (graph.DefaultDepth). */\nexport const CALL_GRAPH_DEFAULT_DEPTH = 2;\n\nexport const DEFAULT_EDGE_LABELS: CallGraphEdgeLabels = { call: \"call\", dispatch: \"dispatch\", read: \"read\", write: \"write\" };\n\n/** The tone each edge type but a plain call is drawn in: dispatch blue, a read green, a write amber. */\nconst EDGE_TONE: Record<Exclude<CallGraphEdgeType, \"call\">, BadgeTone> = { dispatch: \"info\", read: \"success\", write: \"warning\" };\n\n/** Turns one access type on or off, in the usual order. Turning the last one off fails: a graph follows something. */\nexport function toggleAccess(access: readonly CallGraphAccess[], type: CallGraphAccess): CallGraphAccess[] {\n const on = !access.includes(type);\n if (!on && access.length === 1) throw new Error(`call graph: ${type} is the only access type on`);\n return CALL_GRAPH_ACCESS.filter((entry) => (entry === type ? on : access.includes(entry)));\n}\n\nexport interface GraphView {\n direction: CallGraphDirection;\n /** Nodes further than this many hops from the root are hidden. */\n depth: number;\n /** Node ids shown regardless of `depth`, because a `+N` expansion revealed them. */\n revealed: readonly string[];\n}\n\nexport interface VisibleGraph {\n nodes: CallGraphNode[];\n edges: CallGraphEdge[];\n}\n\nexport interface DiagramOptions extends PillOptions {\n /** Box nodes by their `group`. */\n grouped: boolean;\n}\n\nexport type DiagramNode = GraphDiagramNode & { label: string; level: number; title: string };\nexport type DiagramEdge = GraphDiagramEdge & { dashed: boolean };\nexport type DiagramGroup = GraphDiagramGroup & { title: string };\n\nexport interface Diagram {\n nodes: DiagramNode[];\n edges: DiagramEdge[];\n groups: DiagramGroup[];\n}\n\n/** Draws the glyphs the model chooses. The component supplies icons; the tests supply strings. */\nexport interface DiagramGlyphs {\n /** `words` is the icon's name for a screen reader, such as `external function`. */\n node(glyph: string, words: string): ReactNode;\n /** The pill icon of an edge type; a plain call has none. */\n edge(type: CallGraphEdgeType): ReactNode | undefined;\n group(caption: string): ReactNode;\n}\n\nexport interface DiagramInput {\n graph: CallGraph;\n visible: VisibleGraph;\n direction: CallGraphDirection;\n options: DiagramOptions;\n glyphs: DiagramGlyphs;\n vocabulary: CallGraphVocabulary;\n edgeLabels: CallGraphEdgeLabels;\n}\n\nexport function requireNode(graph: CallGraph, id: string): CallGraphNode {\n const node = graph.nodes.find((candidate) => candidate.id === id);\n if (!node) throw new Error(`call graph: no node \"${id}\"`);\n return node;\n}\n\nfunction inDirection(depth: number, direction: CallGraphDirection): boolean {\n if (direction === \"both\" || depth === 0) return true;\n return direction === \"callees\" ? depth > 0 : depth < 0;\n}\n\n/** The nodes on the requested side within `depth`, plus revealed ones, and the edges between them. */\nexport function visibleGraph(graph: CallGraph, view: GraphView): VisibleGraph {\n const revealed = new Set(view.revealed);\n const nodes = graph.nodes.filter(\n (node) => inDirection(node.depth, view.direction) && (Math.abs(node.depth) <= view.depth || revealed.has(node.id)),\n );\n const ids = new Set(nodes.map((node) => node.id));\n return { nodes, edges: graph.edges.filter((edge) => ids.has(edge.from) && ids.has(edge.to)) };\n}\n\n/** A caller grows toward its own callers; the root and callees grow toward their callees. */\nfunction outerSide(node: CallGraphNode): \"in\" | \"out\" {\n return node.depth < 0 ? \"in\" : \"out\";\n}\n\n/** The direction a `+N` expansion of the node walks: its outer side, the side `+N` counts. */\nexport function expansionDirection(node: CallGraphNode): Exclude<CallGraphDirection, \"both\"> {\n return outerSide(node) === \"in\" ? \"callers\" : \"callees\";\n}\n\n/** The ids at the far end of a node's edges on its outer side, as the response holds them. */\nfunction outerNeighbours(graph: CallGraph, node: CallGraphNode): string[] {\n const side = outerSide(node);\n return graph.edges.filter((edge) => (side === \"out\" ? edge.from : edge.to) === node.id).map((edge) => (side === \"out\" ? edge.to : edge.from));\n}\n\n/** The neighbours on a node's outer side that the response holds and are not drawn. */\nexport function hiddenNeighbours(graph: CallGraph, visible: VisibleGraph, nodeId: string): string[] {\n const drawn = new Set(visible.nodes.map((node) => node.id));\n return outerNeighbours(graph, requireNode(graph, nodeId)).filter((id, index, all) => !drawn.has(id) && all.indexOf(id) === index);\n}\n\n/**\n * The `+N` on a node: how many more edges there are to load on its outer side. Only that side's count\n * is a total (`out` for the root and callees, `in` for callers); the other equals the edges in the\n * response. Excluded neighbours are in neither. From it come off the edges drawn. A node without a\n * source cannot be expanded, nor can the side the direction hides.\n */\nexport function expandCount(\n graph: CallGraph,\n visible: VisibleGraph,\n nodeId: string,\n direction: CallGraphDirection,\n vocabulary: Pick<CallGraphVocabulary, \"hasSource\">,\n): number {\n const node = requireNode(graph, nodeId);\n const side = outerSide(node);\n if (!vocabulary.hasSource(node) || direction === (side === \"out\" ? \"callers\" : \"callees\")) return 0;\n const drawn = new Set(visible.nodes.map((entry) => entry.id));\n const accounted = outerNeighbours(graph, node).filter((id) => drawn.has(id)).length;\n return Math.max(0, (side === \"out\" ? node.out : node.in) - accounted);\n}\n\nexport interface NodeTotals {\n callers?: number;\n callees?: number;\n readers?: number;\n writers?: number;\n}\n\n/**\n * A data node's readers, writers and callers: the edges into it the graph holds, by type, each left\n * out when there are none.\n */\nfunction accessTotals(graph: CallGraph, node: CallGraphNode): NodeTotals {\n const into = (types: readonly CallGraphEdgeType[]) => graph.edges.filter((edge) => edge.to === node.id && types.includes(edge.type)).length;\n const totals: [keyof NodeTotals, number][] = [[\"readers\", into([\"read\"])], [\"writers\", into([\"write\"])], [\"callers\", into([\"call\", \"dispatch\"])]];\n return Object.fromEntries(totals.filter(([, count]) => count > 0));\n}\n\n/**\n * A node's call totals on the sides the response walked: callees at depth >= 0, callers at depth <= 0.\n * A data node counts who reads, writes and calls it instead.\n */\nexport function walkedTotals(graph: CallGraph, node: CallGraphNode, vocabulary: Pick<CallGraphVocabulary, \"isData\">): NodeTotals {\n if (vocabulary.isData(node)) return accessTotals(graph, node);\n const walked = (sign: number) => graph.nodes.some((other) => Math.sign(other.depth) === sign);\n return {\n ...(node.depth <= 0 && walked(-1) ? { callers: node.in } : {}),\n ...(node.depth >= 0 && walked(1) ? { callees: node.out } : {}),\n };\n}\n\nfunction distinctSites(sites: CallGraphSite[]): CallGraphSite[] {\n return sites.filter((site, index) => sites.findIndex((other) => siteKey(other) === siteKey(site)) === index);\n}\n\nconst edgeKey = (edge: CallGraphEdge) => `${edge.from}|${edge.to}|${edge.type}`;\n\n/**\n * Merges a one-hop expansion into the held graph. The expansion is rooted at a held node, so its\n * depths are re-signed from that node's depth. Held nodes keep their place; edges are keyed by\n * `from|to|type`, gain the call sites they did not hold and keep their first non-empty properties;\n * the held response's other fields stay.\n */\nexport function mergeGraph<T extends CallGraph>(held: T, expansion: CallGraph): T {\n const [rootId] = expansion.roots;\n const base = held.nodes.find((node) => node.id === rootId);\n if (rootId === undefined || !base) throw new Error(`call graph: expansion root \"${rootId}\" is not in the held graph`);\n const heldIds = new Set(held.nodes.map((node) => node.id));\n const added = expansion.nodes.filter((node) => !heldIds.has(node.id)).map((node) => ({ ...node, depth: base.depth + node.depth }));\n const incoming = new Map(expansion.edges.map((edge) => [edgeKey(edge), edge]));\n const edges = held.edges.map((edge) => {\n const more = incoming.get(edgeKey(edge));\n incoming.delete(edgeKey(edge));\n if (!more) return edge;\n const properties = edge.properties && Object.keys(edge.properties).length > 0 ? edge.properties : more.properties;\n return { ...edge, sites: distinctSites([...edge.sites, ...more.sites]), ...(properties ? { properties } : {}) };\n });\n const groupIds = new Set((held.groups ?? []).map((group) => group.id));\n const groups: CallGraphGroup[] = [...(held.groups ?? []), ...(expansion.groups ?? []).filter((group) => !groupIds.has(group.id))];\n return { ...held, nodes: [...held.nodes, ...added], edges: [...edges, ...incoming.values()], groups };\n}\n\n/**\n * The order nodes are handed to the diagram, which stacks groups in the order they first appear: the\n * root's group, then the other groups holding nodes with a source, then the others, then nodes in no group.\n */\nfunction groupRank(graph: CallGraph, vocabulary: CallGraphVocabulary): (node: CallGraphNode) => number {\n const rootGroups = new Set(graph.roots.map((id) => requireNode(graph, id).group));\n const sourced = new Set(graph.nodes.filter((node) => vocabulary.hasSource(node)).map((node) => node.group));\n return (node) => {\n if (node.group === undefined) return 3;\n if (rootGroups.has(node.group)) return 0;\n return sourced.has(node.group) ? 1 : 2;\n };\n}\n\nfunction toDiagramNode(node: CallGraphNode, { graph, visible, direction, options, glyphs, vocabulary }: DiagramInput): DiagramNode {\n const count = expandCount(graph, visible, node.id, direction, vocabulary);\n const isRoot = graph.roots.includes(node.id);\n const tone = isRoot ? \"info\" : node.unresolved ? \"warning\" : undefined;\n // A table, column, entity or field is a name its group box already places: one short line will do.\n const compact = !isRoot && vocabulary.isData(node) && !vocabulary.hasSource(node);\n return {\n id: node.id,\n label: node.label,\n icon: glyphs.node(vocabulary.glyphOf(graph, node), vocabulary.kindOf(graph, node)),\n title: nodeTitle(graph, node, vocabulary),\n level: node.depth,\n ...(options.grouped && node.group !== undefined ? { group: node.group } : {}),\n ...(compact ? { size: \"compact\" as const } : {}),\n ...(tone !== undefined ? { tone } : {}),\n ...(vocabulary.muted(node) ? { muted: true } : {}),\n ...(count > 0 ? { expandCount: count } : {}),\n };\n}\n\nfunction toDiagramEdge(edge: CallGraphEdge, { options, glyphs, edgeLabels }: DiagramInput): DiagramEdge {\n const label = edgeLabel(edge, options);\n const title = edgeTitle(edge);\n return {\n id: edge.id,\n from: edge.from,\n to: edge.to,\n dashed: isConditional(edge),\n ...(edge.type === \"call\" ? {} : { tone: EDGE_TONE[edge.type], icon: glyphs.edge(edge.type), iconLabel: edgeLabels[edge.type] }),\n ...(label !== undefined ? { label } : {}),\n ...(title !== undefined ? { title } : {}),\n };\n}\n\n/** Mean glyph advance of the 10px pill text, and the pill's padding plus a little air. */\nconst PILL_CHAR_WIDTH = 5.2;\nconst PILL_CHROME = 22;\n/** The room a pill's icon and its gap take, in characters. */\nconst PILL_ICON_CHARS = 3;\nconst MIN_COLUMN_GAP = 96;\n\n/**\n * The gap between columns: as wide as the longest pill on an edge between two columns, so no pill\n * covers a node. Wider gaps than the pills need make the diagram wider, and so smaller once fitted.\n */\nexport function columnGap({\n nodes,\n edges,\n}: {\n nodes: readonly Pick<DiagramNode, \"id\" | \"level\">[];\n edges: readonly Pick<DiagramEdge, \"id\" | \"from\" | \"to\" | \"label\" | \"icon\">[];\n}): number {\n const level = new Map(nodes.map((node) => [node.id, node.level]));\n const chars = edges\n .filter((edge) => level.get(edge.from) !== level.get(edge.to))\n .map((edge) => (edge.label?.length ?? 0) + (edge.icon != null ? PILL_ICON_CHARS : 0));\n return Math.max(MIN_COLUMN_GAP, Math.round(Math.max(0, ...chars) * PILL_CHAR_WIDTH) + PILL_CHROME);\n}\n\nexport function toDiagram(input: DiagramInput): Diagram {\n const { graph, visible, options, glyphs, vocabulary } = input;\n const rank = groupRank(graph, vocabulary);\n return {\n nodes: [...visible.nodes].sort((a, b) => rank(a) - rank(b)).map((node) => toDiagramNode(node, input)),\n edges: visible.edges.map((edge) => toDiagramEdge(edge, input)),\n groups: options.grouped ? (graph.groups ?? []).map(({ id, label }) => ({ id, label: glyphs.group(groupCaption(label)), title: label })) : [],\n };\n}\n"],"names":["CALL_GRAPH_ACCESS","types","siteKey","nodeTitle","edgeLabel","edgeTitle","isConditional","groupCaption"],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { GraphDiagramEdge, GraphDiagramGroup, GraphDiagramNode } from '../graph-diagram-model.js';
|
|
3
|
+
import { PillOptions } from './call-graph-labels.js';
|
|
4
|
+
import { CallGraphVocabulary } from './call-graph-vocabulary.js';
|
|
5
|
+
import { CallGraph, CallGraphAccess, CallGraphDirection, CallGraphEdge, CallGraphEdgeLabels, CallGraphEdgeType, CallGraphNode } from './types.js';
|
|
6
|
+
/** The deepest graph uir builds (graph.MaxDepth). */
|
|
7
|
+
export declare const CALL_GRAPH_MAX_DEPTH = 8;
|
|
8
|
+
/** The depth uir builds when none is asked for (graph.DefaultDepth). */
|
|
9
|
+
export declare const CALL_GRAPH_DEFAULT_DEPTH = 2;
|
|
10
|
+
export declare const DEFAULT_EDGE_LABELS: CallGraphEdgeLabels;
|
|
11
|
+
/** Turns one access type on or off, in the usual order. Turning the last one off fails: a graph follows something. */
|
|
12
|
+
export declare function toggleAccess(access: readonly CallGraphAccess[], type: CallGraphAccess): CallGraphAccess[];
|
|
13
|
+
export interface GraphView {
|
|
14
|
+
direction: CallGraphDirection;
|
|
15
|
+
/** Nodes further than this many hops from the root are hidden. */
|
|
16
|
+
depth: number;
|
|
17
|
+
/** Node ids shown regardless of `depth`, because a `+N` expansion revealed them. */
|
|
18
|
+
revealed: readonly string[];
|
|
19
|
+
}
|
|
20
|
+
export interface VisibleGraph {
|
|
21
|
+
nodes: CallGraphNode[];
|
|
22
|
+
edges: CallGraphEdge[];
|
|
23
|
+
}
|
|
24
|
+
export interface DiagramOptions extends PillOptions {
|
|
25
|
+
/** Box nodes by their `group`. */
|
|
26
|
+
grouped: boolean;
|
|
27
|
+
}
|
|
28
|
+
export type DiagramNode = GraphDiagramNode & {
|
|
29
|
+
label: string;
|
|
30
|
+
level: number;
|
|
31
|
+
title: string;
|
|
32
|
+
};
|
|
33
|
+
export type DiagramEdge = GraphDiagramEdge & {
|
|
34
|
+
dashed: boolean;
|
|
35
|
+
};
|
|
36
|
+
export type DiagramGroup = GraphDiagramGroup & {
|
|
37
|
+
title: string;
|
|
38
|
+
};
|
|
39
|
+
export interface Diagram {
|
|
40
|
+
nodes: DiagramNode[];
|
|
41
|
+
edges: DiagramEdge[];
|
|
42
|
+
groups: DiagramGroup[];
|
|
43
|
+
}
|
|
44
|
+
/** Draws the glyphs the model chooses. The component supplies icons; the tests supply strings. */
|
|
45
|
+
export interface DiagramGlyphs {
|
|
46
|
+
/** `words` is the icon's name for a screen reader, such as `external function`. */
|
|
47
|
+
node(glyph: string, words: string): ReactNode;
|
|
48
|
+
/** The pill icon of an edge type; a plain call has none. */
|
|
49
|
+
edge(type: CallGraphEdgeType): ReactNode | undefined;
|
|
50
|
+
group(caption: string): ReactNode;
|
|
51
|
+
}
|
|
52
|
+
export interface DiagramInput {
|
|
53
|
+
graph: CallGraph;
|
|
54
|
+
visible: VisibleGraph;
|
|
55
|
+
direction: CallGraphDirection;
|
|
56
|
+
options: DiagramOptions;
|
|
57
|
+
glyphs: DiagramGlyphs;
|
|
58
|
+
vocabulary: CallGraphVocabulary;
|
|
59
|
+
edgeLabels: CallGraphEdgeLabels;
|
|
60
|
+
}
|
|
61
|
+
export declare function requireNode(graph: CallGraph, id: string): CallGraphNode;
|
|
62
|
+
/** The nodes on the requested side within `depth`, plus revealed ones, and the edges between them. */
|
|
63
|
+
export declare function visibleGraph(graph: CallGraph, view: GraphView): VisibleGraph;
|
|
64
|
+
/** The direction a `+N` expansion of the node walks: its outer side, the side `+N` counts. */
|
|
65
|
+
export declare function expansionDirection(node: CallGraphNode): Exclude<CallGraphDirection, "both">;
|
|
66
|
+
/** The neighbours on a node's outer side that the response holds and are not drawn. */
|
|
67
|
+
export declare function hiddenNeighbours(graph: CallGraph, visible: VisibleGraph, nodeId: string): string[];
|
|
68
|
+
/**
|
|
69
|
+
* The `+N` on a node: how many more edges there are to load on its outer side. Only that side's count
|
|
70
|
+
* is a total (`out` for the root and callees, `in` for callers); the other equals the edges in the
|
|
71
|
+
* response. Excluded neighbours are in neither. From it come off the edges drawn. A node without a
|
|
72
|
+
* source cannot be expanded, nor can the side the direction hides.
|
|
73
|
+
*/
|
|
74
|
+
export declare function expandCount(graph: CallGraph, visible: VisibleGraph, nodeId: string, direction: CallGraphDirection, vocabulary: Pick<CallGraphVocabulary, "hasSource">): number;
|
|
75
|
+
export interface NodeTotals {
|
|
76
|
+
callers?: number;
|
|
77
|
+
callees?: number;
|
|
78
|
+
readers?: number;
|
|
79
|
+
writers?: number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* A node's call totals on the sides the response walked: callees at depth >= 0, callers at depth <= 0.
|
|
83
|
+
* A data node counts who reads, writes and calls it instead.
|
|
84
|
+
*/
|
|
85
|
+
export declare function walkedTotals(graph: CallGraph, node: CallGraphNode, vocabulary: Pick<CallGraphVocabulary, "isData">): NodeTotals;
|
|
86
|
+
/**
|
|
87
|
+
* Merges a one-hop expansion into the held graph. The expansion is rooted at a held node, so its
|
|
88
|
+
* depths are re-signed from that node's depth. Held nodes keep their place; edges are keyed by
|
|
89
|
+
* `from|to|type`, gain the call sites they did not hold and keep their first non-empty properties;
|
|
90
|
+
* the held response's other fields stay.
|
|
91
|
+
*/
|
|
92
|
+
export declare function mergeGraph<T extends CallGraph>(held: T, expansion: CallGraph): T;
|
|
93
|
+
/**
|
|
94
|
+
* The gap between columns: as wide as the longest pill on an edge between two columns, so no pill
|
|
95
|
+
* covers a node. Wider gaps than the pills need make the diagram wider, and so smaller once fitted.
|
|
96
|
+
*/
|
|
97
|
+
export declare function columnGap({ nodes, edges, }: {
|
|
98
|
+
nodes: readonly Pick<DiagramNode, "id" | "level">[];
|
|
99
|
+
edges: readonly Pick<DiagramEdge, "id" | "from" | "to" | "label" | "icon">[];
|
|
100
|
+
}): number;
|
|
101
|
+
export declare function toDiagram(input: DiagramInput): Diagram;
|
|
102
|
+
//# sourceMappingURL=call-graph-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-graph-model.d.ts","sourceRoot":"","sources":["../../../src/data/call-graph/call-graph-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { groupCaption, edgeLabel, edgeTitle, isConditional } from "./call-graph-labels.js";
|
|
2
|
+
import { siteKey, nodeTitle } from "./call-graph-vocabulary.js";
|
|
3
|
+
import { CALL_GRAPH_ACCESS } from "./types.js";
|
|
4
|
+
const CALL_GRAPH_MAX_DEPTH = 8;
|
|
5
|
+
const CALL_GRAPH_DEFAULT_DEPTH = 2;
|
|
6
|
+
const DEFAULT_EDGE_LABELS = { call: "call", dispatch: "dispatch", read: "read", write: "write" };
|
|
7
|
+
const EDGE_TONE = { dispatch: "info", read: "success", write: "warning" };
|
|
8
|
+
function toggleAccess(access, type) {
|
|
9
|
+
const on = !access.includes(type);
|
|
10
|
+
if (!on && access.length === 1) throw new Error(`call graph: ${type} is the only access type on`);
|
|
11
|
+
return CALL_GRAPH_ACCESS.filter((entry) => entry === type ? on : access.includes(entry));
|
|
12
|
+
}
|
|
13
|
+
function requireNode(graph, id) {
|
|
14
|
+
const node = graph.nodes.find((candidate) => candidate.id === id);
|
|
15
|
+
if (!node) throw new Error(`call graph: no node "${id}"`);
|
|
16
|
+
return node;
|
|
17
|
+
}
|
|
18
|
+
function inDirection(depth, direction) {
|
|
19
|
+
if (direction === "both" || depth === 0) return true;
|
|
20
|
+
return direction === "callees" ? depth > 0 : depth < 0;
|
|
21
|
+
}
|
|
22
|
+
function visibleGraph(graph, view) {
|
|
23
|
+
const revealed = new Set(view.revealed);
|
|
24
|
+
const nodes = graph.nodes.filter(
|
|
25
|
+
(node) => inDirection(node.depth, view.direction) && (Math.abs(node.depth) <= view.depth || revealed.has(node.id))
|
|
26
|
+
);
|
|
27
|
+
const ids = new Set(nodes.map((node) => node.id));
|
|
28
|
+
return { nodes, edges: graph.edges.filter((edge) => ids.has(edge.from) && ids.has(edge.to)) };
|
|
29
|
+
}
|
|
30
|
+
function outerSide(node) {
|
|
31
|
+
return node.depth < 0 ? "in" : "out";
|
|
32
|
+
}
|
|
33
|
+
function expansionDirection(node) {
|
|
34
|
+
return outerSide(node) === "in" ? "callers" : "callees";
|
|
35
|
+
}
|
|
36
|
+
function outerNeighbours(graph, node) {
|
|
37
|
+
const side = outerSide(node);
|
|
38
|
+
return graph.edges.filter((edge) => (side === "out" ? edge.from : edge.to) === node.id).map((edge) => side === "out" ? edge.to : edge.from);
|
|
39
|
+
}
|
|
40
|
+
function expandCount(graph, visible, nodeId, direction, vocabulary) {
|
|
41
|
+
const node = requireNode(graph, nodeId);
|
|
42
|
+
const side = outerSide(node);
|
|
43
|
+
if (!vocabulary.hasSource(node) || direction === (side === "out" ? "callers" : "callees")) return 0;
|
|
44
|
+
const drawn = new Set(visible.nodes.map((entry) => entry.id));
|
|
45
|
+
const accounted = outerNeighbours(graph, node).filter((id) => drawn.has(id)).length;
|
|
46
|
+
return Math.max(0, (side === "out" ? node.out : node.in) - accounted);
|
|
47
|
+
}
|
|
48
|
+
function accessTotals(graph, node) {
|
|
49
|
+
const into = (types) => graph.edges.filter((edge) => edge.to === node.id && types.includes(edge.type)).length;
|
|
50
|
+
const totals = [["readers", into(["read"])], ["writers", into(["write"])], ["callers", into(["call", "dispatch"])]];
|
|
51
|
+
return Object.fromEntries(totals.filter(([, count]) => count > 0));
|
|
52
|
+
}
|
|
53
|
+
function walkedTotals(graph, node, vocabulary) {
|
|
54
|
+
if (vocabulary.isData(node)) return accessTotals(graph, node);
|
|
55
|
+
const walked = (sign) => graph.nodes.some((other) => Math.sign(other.depth) === sign);
|
|
56
|
+
return {
|
|
57
|
+
...node.depth <= 0 && walked(-1) ? { callers: node.in } : {},
|
|
58
|
+
...node.depth >= 0 && walked(1) ? { callees: node.out } : {}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function distinctSites(sites) {
|
|
62
|
+
return sites.filter((site, index) => sites.findIndex((other) => siteKey(other) === siteKey(site)) === index);
|
|
63
|
+
}
|
|
64
|
+
const edgeKey = (edge) => `${edge.from}|${edge.to}|${edge.type}`;
|
|
65
|
+
function mergeGraph(held, expansion) {
|
|
66
|
+
const [rootId] = expansion.roots;
|
|
67
|
+
const base = held.nodes.find((node) => node.id === rootId);
|
|
68
|
+
if (rootId === void 0 || !base) throw new Error(`call graph: expansion root "${rootId}" is not in the held graph`);
|
|
69
|
+
const heldIds = new Set(held.nodes.map((node) => node.id));
|
|
70
|
+
const added = expansion.nodes.filter((node) => !heldIds.has(node.id)).map((node) => ({ ...node, depth: base.depth + node.depth }));
|
|
71
|
+
const incoming = new Map(expansion.edges.map((edge) => [edgeKey(edge), edge]));
|
|
72
|
+
const edges = held.edges.map((edge) => {
|
|
73
|
+
const more = incoming.get(edgeKey(edge));
|
|
74
|
+
incoming.delete(edgeKey(edge));
|
|
75
|
+
if (!more) return edge;
|
|
76
|
+
const properties = edge.properties && Object.keys(edge.properties).length > 0 ? edge.properties : more.properties;
|
|
77
|
+
return { ...edge, sites: distinctSites([...edge.sites, ...more.sites]), ...properties ? { properties } : {} };
|
|
78
|
+
});
|
|
79
|
+
const groupIds = new Set((held.groups ?? []).map((group) => group.id));
|
|
80
|
+
const groups = [...held.groups ?? [], ...(expansion.groups ?? []).filter((group) => !groupIds.has(group.id))];
|
|
81
|
+
return { ...held, nodes: [...held.nodes, ...added], edges: [...edges, ...incoming.values()], groups };
|
|
82
|
+
}
|
|
83
|
+
function groupRank(graph, vocabulary) {
|
|
84
|
+
const rootGroups = new Set(graph.roots.map((id) => requireNode(graph, id).group));
|
|
85
|
+
const sourced = new Set(graph.nodes.filter((node) => vocabulary.hasSource(node)).map((node) => node.group));
|
|
86
|
+
return (node) => {
|
|
87
|
+
if (node.group === void 0) return 3;
|
|
88
|
+
if (rootGroups.has(node.group)) return 0;
|
|
89
|
+
return sourced.has(node.group) ? 1 : 2;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function toDiagramNode(node, { graph, visible, direction, options, glyphs, vocabulary }) {
|
|
93
|
+
const count = expandCount(graph, visible, node.id, direction, vocabulary);
|
|
94
|
+
const isRoot = graph.roots.includes(node.id);
|
|
95
|
+
const tone = isRoot ? "info" : node.unresolved ? "warning" : void 0;
|
|
96
|
+
const compact = !isRoot && vocabulary.isData(node) && !vocabulary.hasSource(node);
|
|
97
|
+
return {
|
|
98
|
+
id: node.id,
|
|
99
|
+
label: node.label,
|
|
100
|
+
icon: glyphs.node(vocabulary.glyphOf(graph, node), vocabulary.kindOf(graph, node)),
|
|
101
|
+
title: nodeTitle(graph, node, vocabulary),
|
|
102
|
+
level: node.depth,
|
|
103
|
+
...options.grouped && node.group !== void 0 ? { group: node.group } : {},
|
|
104
|
+
...compact ? { size: "compact" } : {},
|
|
105
|
+
...tone !== void 0 ? { tone } : {},
|
|
106
|
+
...vocabulary.muted(node) ? { muted: true } : {},
|
|
107
|
+
...count > 0 ? { expandCount: count } : {}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function toDiagramEdge(edge, { options, glyphs, edgeLabels }) {
|
|
111
|
+
const label = edgeLabel(edge, options);
|
|
112
|
+
const title = edgeTitle(edge);
|
|
113
|
+
return {
|
|
114
|
+
id: edge.id,
|
|
115
|
+
from: edge.from,
|
|
116
|
+
to: edge.to,
|
|
117
|
+
dashed: isConditional(edge),
|
|
118
|
+
...edge.type === "call" ? {} : { tone: EDGE_TONE[edge.type], icon: glyphs.edge(edge.type), iconLabel: edgeLabels[edge.type] },
|
|
119
|
+
...label !== void 0 ? { label } : {},
|
|
120
|
+
...title !== void 0 ? { title } : {}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const PILL_CHAR_WIDTH = 5.2;
|
|
124
|
+
const PILL_CHROME = 22;
|
|
125
|
+
const PILL_ICON_CHARS = 3;
|
|
126
|
+
const MIN_COLUMN_GAP = 96;
|
|
127
|
+
function columnGap({
|
|
128
|
+
nodes,
|
|
129
|
+
edges
|
|
130
|
+
}) {
|
|
131
|
+
const level = new Map(nodes.map((node) => [node.id, node.level]));
|
|
132
|
+
const chars = edges.filter((edge) => level.get(edge.from) !== level.get(edge.to)).map((edge) => {
|
|
133
|
+
var _a;
|
|
134
|
+
return (((_a = edge.label) == null ? void 0 : _a.length) ?? 0) + (edge.icon != null ? PILL_ICON_CHARS : 0);
|
|
135
|
+
});
|
|
136
|
+
return Math.max(MIN_COLUMN_GAP, Math.round(Math.max(0, ...chars) * PILL_CHAR_WIDTH) + PILL_CHROME);
|
|
137
|
+
}
|
|
138
|
+
function toDiagram(input) {
|
|
139
|
+
const { graph, visible, options, glyphs, vocabulary } = input;
|
|
140
|
+
const rank = groupRank(graph, vocabulary);
|
|
141
|
+
return {
|
|
142
|
+
nodes: [...visible.nodes].sort((a, b) => rank(a) - rank(b)).map((node) => toDiagramNode(node, input)),
|
|
143
|
+
edges: visible.edges.map((edge) => toDiagramEdge(edge, input)),
|
|
144
|
+
groups: options.grouped ? (graph.groups ?? []).map(({ id, label }) => ({ id, label: glyphs.group(groupCaption(label)), title: label })) : []
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
export {
|
|
148
|
+
CALL_GRAPH_DEFAULT_DEPTH,
|
|
149
|
+
CALL_GRAPH_MAX_DEPTH,
|
|
150
|
+
DEFAULT_EDGE_LABELS,
|
|
151
|
+
columnGap,
|
|
152
|
+
expandCount,
|
|
153
|
+
expansionDirection,
|
|
154
|
+
mergeGraph,
|
|
155
|
+
requireNode,
|
|
156
|
+
toDiagram,
|
|
157
|
+
toggleAccess,
|
|
158
|
+
visibleGraph,
|
|
159
|
+
walkedTotals
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=call-graph-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-graph-model.js","sources":["../../../src/data/call-graph/call-graph-model.ts"],"sourcesContent":["// Pure mapping from a call graph to what GraphDiagram draws, and how a `+N` expansion merges into the\n// held graph. It decides what is shown and leaves drawing a glyph to the DiagramGlyphs it is handed,\n// so it renders nothing itself.\nimport type { ReactNode } from \"react\";\nimport type { BadgeTone } from \"../Badge\";\nimport type { GraphDiagramEdge, GraphDiagramGroup, GraphDiagramNode } from \"../graph-diagram-model\";\nimport { edgeLabel, edgeTitle, groupCaption, isConditional, type PillOptions } from \"./call-graph-labels\";\nimport { nodeTitle, siteKey, type CallGraphVocabulary } from \"./call-graph-vocabulary\";\nimport {\n CALL_GRAPH_ACCESS,\n type CallGraph,\n type CallGraphAccess,\n type CallGraphDirection,\n type CallGraphEdge,\n type CallGraphEdgeLabels,\n type CallGraphEdgeType,\n type CallGraphGroup,\n type CallGraphNode,\n type CallGraphSite,\n} from \"./types\";\n\n/** The deepest graph uir builds (graph.MaxDepth). */\nexport const CALL_GRAPH_MAX_DEPTH = 8;\n/** The depth uir builds when none is asked for (graph.DefaultDepth). */\nexport const CALL_GRAPH_DEFAULT_DEPTH = 2;\n\nexport const DEFAULT_EDGE_LABELS: CallGraphEdgeLabels = { call: \"call\", dispatch: \"dispatch\", read: \"read\", write: \"write\" };\n\n/** The tone each edge type but a plain call is drawn in: dispatch blue, a read green, a write amber. */\nconst EDGE_TONE: Record<Exclude<CallGraphEdgeType, \"call\">, BadgeTone> = { dispatch: \"info\", read: \"success\", write: \"warning\" };\n\n/** Turns one access type on or off, in the usual order. Turning the last one off fails: a graph follows something. */\nexport function toggleAccess(access: readonly CallGraphAccess[], type: CallGraphAccess): CallGraphAccess[] {\n const on = !access.includes(type);\n if (!on && access.length === 1) throw new Error(`call graph: ${type} is the only access type on`);\n return CALL_GRAPH_ACCESS.filter((entry) => (entry === type ? on : access.includes(entry)));\n}\n\nexport interface GraphView {\n direction: CallGraphDirection;\n /** Nodes further than this many hops from the root are hidden. */\n depth: number;\n /** Node ids shown regardless of `depth`, because a `+N` expansion revealed them. */\n revealed: readonly string[];\n}\n\nexport interface VisibleGraph {\n nodes: CallGraphNode[];\n edges: CallGraphEdge[];\n}\n\nexport interface DiagramOptions extends PillOptions {\n /** Box nodes by their `group`. */\n grouped: boolean;\n}\n\nexport type DiagramNode = GraphDiagramNode & { label: string; level: number; title: string };\nexport type DiagramEdge = GraphDiagramEdge & { dashed: boolean };\nexport type DiagramGroup = GraphDiagramGroup & { title: string };\n\nexport interface Diagram {\n nodes: DiagramNode[];\n edges: DiagramEdge[];\n groups: DiagramGroup[];\n}\n\n/** Draws the glyphs the model chooses. The component supplies icons; the tests supply strings. */\nexport interface DiagramGlyphs {\n /** `words` is the icon's name for a screen reader, such as `external function`. */\n node(glyph: string, words: string): ReactNode;\n /** The pill icon of an edge type; a plain call has none. */\n edge(type: CallGraphEdgeType): ReactNode | undefined;\n group(caption: string): ReactNode;\n}\n\nexport interface DiagramInput {\n graph: CallGraph;\n visible: VisibleGraph;\n direction: CallGraphDirection;\n options: DiagramOptions;\n glyphs: DiagramGlyphs;\n vocabulary: CallGraphVocabulary;\n edgeLabels: CallGraphEdgeLabels;\n}\n\nexport function requireNode(graph: CallGraph, id: string): CallGraphNode {\n const node = graph.nodes.find((candidate) => candidate.id === id);\n if (!node) throw new Error(`call graph: no node \"${id}\"`);\n return node;\n}\n\nfunction inDirection(depth: number, direction: CallGraphDirection): boolean {\n if (direction === \"both\" || depth === 0) return true;\n return direction === \"callees\" ? depth > 0 : depth < 0;\n}\n\n/** The nodes on the requested side within `depth`, plus revealed ones, and the edges between them. */\nexport function visibleGraph(graph: CallGraph, view: GraphView): VisibleGraph {\n const revealed = new Set(view.revealed);\n const nodes = graph.nodes.filter(\n (node) => inDirection(node.depth, view.direction) && (Math.abs(node.depth) <= view.depth || revealed.has(node.id)),\n );\n const ids = new Set(nodes.map((node) => node.id));\n return { nodes, edges: graph.edges.filter((edge) => ids.has(edge.from) && ids.has(edge.to)) };\n}\n\n/** A caller grows toward its own callers; the root and callees grow toward their callees. */\nfunction outerSide(node: CallGraphNode): \"in\" | \"out\" {\n return node.depth < 0 ? \"in\" : \"out\";\n}\n\n/** The direction a `+N` expansion of the node walks: its outer side, the side `+N` counts. */\nexport function expansionDirection(node: CallGraphNode): Exclude<CallGraphDirection, \"both\"> {\n return outerSide(node) === \"in\" ? \"callers\" : \"callees\";\n}\n\n/** The ids at the far end of a node's edges on its outer side, as the response holds them. */\nfunction outerNeighbours(graph: CallGraph, node: CallGraphNode): string[] {\n const side = outerSide(node);\n return graph.edges.filter((edge) => (side === \"out\" ? edge.from : edge.to) === node.id).map((edge) => (side === \"out\" ? edge.to : edge.from));\n}\n\n/** The neighbours on a node's outer side that the response holds and are not drawn. */\nexport function hiddenNeighbours(graph: CallGraph, visible: VisibleGraph, nodeId: string): string[] {\n const drawn = new Set(visible.nodes.map((node) => node.id));\n return outerNeighbours(graph, requireNode(graph, nodeId)).filter((id, index, all) => !drawn.has(id) && all.indexOf(id) === index);\n}\n\n/**\n * The `+N` on a node: how many more edges there are to load on its outer side. Only that side's count\n * is a total (`out` for the root and callees, `in` for callers); the other equals the edges in the\n * response. Excluded neighbours are in neither. From it come off the edges drawn. A node without a\n * source cannot be expanded, nor can the side the direction hides.\n */\nexport function expandCount(\n graph: CallGraph,\n visible: VisibleGraph,\n nodeId: string,\n direction: CallGraphDirection,\n vocabulary: Pick<CallGraphVocabulary, \"hasSource\">,\n): number {\n const node = requireNode(graph, nodeId);\n const side = outerSide(node);\n if (!vocabulary.hasSource(node) || direction === (side === \"out\" ? \"callers\" : \"callees\")) return 0;\n const drawn = new Set(visible.nodes.map((entry) => entry.id));\n const accounted = outerNeighbours(graph, node).filter((id) => drawn.has(id)).length;\n return Math.max(0, (side === \"out\" ? node.out : node.in) - accounted);\n}\n\nexport interface NodeTotals {\n callers?: number;\n callees?: number;\n readers?: number;\n writers?: number;\n}\n\n/**\n * A data node's readers, writers and callers: the edges into it the graph holds, by type, each left\n * out when there are none.\n */\nfunction accessTotals(graph: CallGraph, node: CallGraphNode): NodeTotals {\n const into = (types: readonly CallGraphEdgeType[]) => graph.edges.filter((edge) => edge.to === node.id && types.includes(edge.type)).length;\n const totals: [keyof NodeTotals, number][] = [[\"readers\", into([\"read\"])], [\"writers\", into([\"write\"])], [\"callers\", into([\"call\", \"dispatch\"])]];\n return Object.fromEntries(totals.filter(([, count]) => count > 0));\n}\n\n/**\n * A node's call totals on the sides the response walked: callees at depth >= 0, callers at depth <= 0.\n * A data node counts who reads, writes and calls it instead.\n */\nexport function walkedTotals(graph: CallGraph, node: CallGraphNode, vocabulary: Pick<CallGraphVocabulary, \"isData\">): NodeTotals {\n if (vocabulary.isData(node)) return accessTotals(graph, node);\n const walked = (sign: number) => graph.nodes.some((other) => Math.sign(other.depth) === sign);\n return {\n ...(node.depth <= 0 && walked(-1) ? { callers: node.in } : {}),\n ...(node.depth >= 0 && walked(1) ? { callees: node.out } : {}),\n };\n}\n\nfunction distinctSites(sites: CallGraphSite[]): CallGraphSite[] {\n return sites.filter((site, index) => sites.findIndex((other) => siteKey(other) === siteKey(site)) === index);\n}\n\nconst edgeKey = (edge: CallGraphEdge) => `${edge.from}|${edge.to}|${edge.type}`;\n\n/**\n * Merges a one-hop expansion into the held graph. The expansion is rooted at a held node, so its\n * depths are re-signed from that node's depth. Held nodes keep their place; edges are keyed by\n * `from|to|type`, gain the call sites they did not hold and keep their first non-empty properties;\n * the held response's other fields stay.\n */\nexport function mergeGraph<T extends CallGraph>(held: T, expansion: CallGraph): T {\n const [rootId] = expansion.roots;\n const base = held.nodes.find((node) => node.id === rootId);\n if (rootId === undefined || !base) throw new Error(`call graph: expansion root \"${rootId}\" is not in the held graph`);\n const heldIds = new Set(held.nodes.map((node) => node.id));\n const added = expansion.nodes.filter((node) => !heldIds.has(node.id)).map((node) => ({ ...node, depth: base.depth + node.depth }));\n const incoming = new Map(expansion.edges.map((edge) => [edgeKey(edge), edge]));\n const edges = held.edges.map((edge) => {\n const more = incoming.get(edgeKey(edge));\n incoming.delete(edgeKey(edge));\n if (!more) return edge;\n const properties = edge.properties && Object.keys(edge.properties).length > 0 ? edge.properties : more.properties;\n return { ...edge, sites: distinctSites([...edge.sites, ...more.sites]), ...(properties ? { properties } : {}) };\n });\n const groupIds = new Set((held.groups ?? []).map((group) => group.id));\n const groups: CallGraphGroup[] = [...(held.groups ?? []), ...(expansion.groups ?? []).filter((group) => !groupIds.has(group.id))];\n return { ...held, nodes: [...held.nodes, ...added], edges: [...edges, ...incoming.values()], groups };\n}\n\n/**\n * The order nodes are handed to the diagram, which stacks groups in the order they first appear: the\n * root's group, then the other groups holding nodes with a source, then the others, then nodes in no group.\n */\nfunction groupRank(graph: CallGraph, vocabulary: CallGraphVocabulary): (node: CallGraphNode) => number {\n const rootGroups = new Set(graph.roots.map((id) => requireNode(graph, id).group));\n const sourced = new Set(graph.nodes.filter((node) => vocabulary.hasSource(node)).map((node) => node.group));\n return (node) => {\n if (node.group === undefined) return 3;\n if (rootGroups.has(node.group)) return 0;\n return sourced.has(node.group) ? 1 : 2;\n };\n}\n\nfunction toDiagramNode(node: CallGraphNode, { graph, visible, direction, options, glyphs, vocabulary }: DiagramInput): DiagramNode {\n const count = expandCount(graph, visible, node.id, direction, vocabulary);\n const isRoot = graph.roots.includes(node.id);\n const tone = isRoot ? \"info\" : node.unresolved ? \"warning\" : undefined;\n // A table, column, entity or field is a name its group box already places: one short line will do.\n const compact = !isRoot && vocabulary.isData(node) && !vocabulary.hasSource(node);\n return {\n id: node.id,\n label: node.label,\n icon: glyphs.node(vocabulary.glyphOf(graph, node), vocabulary.kindOf(graph, node)),\n title: nodeTitle(graph, node, vocabulary),\n level: node.depth,\n ...(options.grouped && node.group !== undefined ? { group: node.group } : {}),\n ...(compact ? { size: \"compact\" as const } : {}),\n ...(tone !== undefined ? { tone } : {}),\n ...(vocabulary.muted(node) ? { muted: true } : {}),\n ...(count > 0 ? { expandCount: count } : {}),\n };\n}\n\nfunction toDiagramEdge(edge: CallGraphEdge, { options, glyphs, edgeLabels }: DiagramInput): DiagramEdge {\n const label = edgeLabel(edge, options);\n const title = edgeTitle(edge);\n return {\n id: edge.id,\n from: edge.from,\n to: edge.to,\n dashed: isConditional(edge),\n ...(edge.type === \"call\" ? {} : { tone: EDGE_TONE[edge.type], icon: glyphs.edge(edge.type), iconLabel: edgeLabels[edge.type] }),\n ...(label !== undefined ? { label } : {}),\n ...(title !== undefined ? { title } : {}),\n };\n}\n\n/** Mean glyph advance of the 10px pill text, and the pill's padding plus a little air. */\nconst PILL_CHAR_WIDTH = 5.2;\nconst PILL_CHROME = 22;\n/** The room a pill's icon and its gap take, in characters. */\nconst PILL_ICON_CHARS = 3;\nconst MIN_COLUMN_GAP = 96;\n\n/**\n * The gap between columns: as wide as the longest pill on an edge between two columns, so no pill\n * covers a node. Wider gaps than the pills need make the diagram wider, and so smaller once fitted.\n */\nexport function columnGap({\n nodes,\n edges,\n}: {\n nodes: readonly Pick<DiagramNode, \"id\" | \"level\">[];\n edges: readonly Pick<DiagramEdge, \"id\" | \"from\" | \"to\" | \"label\" | \"icon\">[];\n}): number {\n const level = new Map(nodes.map((node) => [node.id, node.level]));\n const chars = edges\n .filter((edge) => level.get(edge.from) !== level.get(edge.to))\n .map((edge) => (edge.label?.length ?? 0) + (edge.icon != null ? PILL_ICON_CHARS : 0));\n return Math.max(MIN_COLUMN_GAP, Math.round(Math.max(0, ...chars) * PILL_CHAR_WIDTH) + PILL_CHROME);\n}\n\nexport function toDiagram(input: DiagramInput): Diagram {\n const { graph, visible, options, glyphs, vocabulary } = input;\n const rank = groupRank(graph, vocabulary);\n return {\n nodes: [...visible.nodes].sort((a, b) => rank(a) - rank(b)).map((node) => toDiagramNode(node, input)),\n edges: visible.edges.map((edge) => toDiagramEdge(edge, input)),\n groups: options.grouped ? (graph.groups ?? []).map(({ id, label }) => ({ id, label: glyphs.group(groupCaption(label)), title: label })) : [],\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const UiSqlTable = require("../../icons/components/UiSqlTable.cjs");
|
|
4
|
+
const UiSqlColumn = require("../../icons/components/UiSqlColumn.cjs");
|
|
5
|
+
const UiSqlStoredProc = require("../../icons/components/UiSqlStoredProc.cjs");
|
|
6
|
+
const UiTableProperties = require("../../icons/components/UiTableProperties.cjs");
|
|
7
|
+
const UiField = require("../../icons/components/UiField.cjs");
|
|
8
|
+
const UiPackage = require("../../icons/components/UiPackage.cjs");
|
|
9
|
+
const UiFunction = require("../../icons/components/UiFunction.cjs");
|
|
10
|
+
const UiMethod = require("../../icons/components/UiMethod.cjs");
|
|
11
|
+
const UiInterface = require("../../icons/components/UiInterface.cjs");
|
|
12
|
+
const UiMethod11 = require("../../icons/components/UiMethod11.cjs");
|
|
13
|
+
const UiFunction1 = require("../../icons/components/UiFunction1.cjs");
|
|
14
|
+
const UiFunctionSquare = require("../../icons/components/UiFunctionSquare.cjs");
|
|
15
|
+
const UiTypeParameter = require("../../icons/components/UiTypeParameter.cjs");
|
|
16
|
+
const UiVariable = require("../../icons/components/UiVariable.cjs");
|
|
17
|
+
const UiConstant = require("../../icons/components/UiConstant.cjs");
|
|
18
|
+
const UiUnknown = require("../../icons/components/UiUnknown.cjs");
|
|
19
|
+
const UiSymbol = require("../../icons/components/UiSymbol.cjs");
|
|
20
|
+
function requireGlyph(vocabulary, id) {
|
|
21
|
+
const glyph = vocabulary.glyphs.find((candidate) => candidate.id === id);
|
|
22
|
+
if (!glyph) throw new Error(`call graph: the vocabulary has no glyph "${id}"`);
|
|
23
|
+
return glyph;
|
|
24
|
+
}
|
|
25
|
+
function usedGlyphs(graph, vocabulary) {
|
|
26
|
+
const used = new Set(graph.nodes.map((node) => vocabulary.glyphOf(graph, node)));
|
|
27
|
+
return vocabulary.glyphs.filter((glyph) => used.has(glyph.id));
|
|
28
|
+
}
|
|
29
|
+
function nodeTitle(graph, node, vocabulary) {
|
|
30
|
+
var _a, _b;
|
|
31
|
+
const group = ((_b = (_a = graph.groups) == null ? void 0 : _a.find((candidate) => candidate.id === node.group)) == null ? void 0 : _b.label) ?? node.group;
|
|
32
|
+
return `${vocabulary.kindOf(graph, node)} ${node.label}${group ? ` in ${group}` : ""}`;
|
|
33
|
+
}
|
|
34
|
+
function callsItself(graph, node) {
|
|
35
|
+
return graph.edges.some((edge) => edge.from === node.id && edge.to === node.id);
|
|
36
|
+
}
|
|
37
|
+
function siteKey(site) {
|
|
38
|
+
return `${site.path}:${site.line}:${site.column}`;
|
|
39
|
+
}
|
|
40
|
+
const UIR_KINDS = /* @__PURE__ */ new Map([
|
|
41
|
+
["func", { glyph: "func", words: "function" }],
|
|
42
|
+
["method", { glyph: "method", words: "method" }],
|
|
43
|
+
["builtin", { glyph: "builtin", words: "builtin" }],
|
|
44
|
+
["type", { glyph: "type", words: "type" }],
|
|
45
|
+
["field", { glyph: "field", words: "field" }],
|
|
46
|
+
["var", { glyph: "var", words: "variable" }],
|
|
47
|
+
["const", { glyph: "const", words: "constant" }],
|
|
48
|
+
["package", { glyph: "package", words: "package scope" }]
|
|
49
|
+
]);
|
|
50
|
+
const DATA_KIND_WORDS = {
|
|
51
|
+
table: "table",
|
|
52
|
+
column: "column",
|
|
53
|
+
procedure: "stored procedure",
|
|
54
|
+
entity: "entity",
|
|
55
|
+
field: "field"
|
|
56
|
+
};
|
|
57
|
+
const CALL_GRAPH_DATA_GLYPHS = [
|
|
58
|
+
{ id: "table", name: "table", icon: UiSqlTable.UiSqlTable },
|
|
59
|
+
{ id: "column", name: "column", icon: UiSqlColumn.UiSqlColumn },
|
|
60
|
+
{ id: "procedure", name: "stored procedure", icon: UiSqlStoredProc.UiSqlStoredProc },
|
|
61
|
+
{ id: "entity", name: "entity", icon: UiTableProperties.UiTableProperties },
|
|
62
|
+
{ id: "field", name: "field", icon: UiField.UiField }
|
|
63
|
+
];
|
|
64
|
+
function isDataNode(node) {
|
|
65
|
+
return Object.hasOwn(DATA_KIND_WORDS, node.kind);
|
|
66
|
+
}
|
|
67
|
+
function dataName(node) {
|
|
68
|
+
const prefix = `${node.kind}:`;
|
|
69
|
+
return node.id.startsWith(prefix) ? node.id.slice(prefix.length) : node.label;
|
|
70
|
+
}
|
|
71
|
+
function dataNodeStatus(node) {
|
|
72
|
+
const name = dataName(node);
|
|
73
|
+
switch (node.kind) {
|
|
74
|
+
case "table":
|
|
75
|
+
return `Table ${name}`;
|
|
76
|
+
case "column":
|
|
77
|
+
return `Column ${name}`;
|
|
78
|
+
case "procedure":
|
|
79
|
+
return `Stored procedure ${name}`;
|
|
80
|
+
case "entity":
|
|
81
|
+
return `${name} fields`;
|
|
82
|
+
}
|
|
83
|
+
const entity = name.includes(".") ? name.slice(0, name.indexOf(".")) : node.group ?? "";
|
|
84
|
+
const { column, storage } = node.properties ?? {};
|
|
85
|
+
if (column) return `${entity} field → ${column}`;
|
|
86
|
+
if (storage) return `${entity} field, dynamic, stored in ${storage}`;
|
|
87
|
+
return `${entity} field`;
|
|
88
|
+
}
|
|
89
|
+
function dataNodeBacking(node) {
|
|
90
|
+
var _a;
|
|
91
|
+
const column = node.kind === "field" ? (_a = node.properties) == null ? void 0 : _a.column : void 0;
|
|
92
|
+
return column ? { id: `column:${column}`, label: column } : void 0;
|
|
93
|
+
}
|
|
94
|
+
function isBuiltin(node) {
|
|
95
|
+
return node.kind === "builtin";
|
|
96
|
+
}
|
|
97
|
+
function isPackageScope(node) {
|
|
98
|
+
return node.kind === "package";
|
|
99
|
+
}
|
|
100
|
+
function isExternal(node) {
|
|
101
|
+
return !node.location && !node.unresolved && !isBuiltin(node) && !isPackageScope(node) && !isDataNode(node);
|
|
102
|
+
}
|
|
103
|
+
function interfaceMethods(graph) {
|
|
104
|
+
const dispatched = new Set(
|
|
105
|
+
graph.edges.filter((edge) => edge.type === "dispatch").flatMap((edge) => edge.sites.map((site) => `${edge.from} ${siteKey(site)}`))
|
|
106
|
+
);
|
|
107
|
+
return new Set(
|
|
108
|
+
graph.edges.filter((edge) => edge.type === "call" && edge.sites.some((site) => dispatched.has(`${edge.from} ${siteKey(site)}`))).map((edge) => edge.to)
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
function uirGlyph(graph, node) {
|
|
112
|
+
var _a;
|
|
113
|
+
if (node.unresolved) return "unresolved";
|
|
114
|
+
if (isBuiltin(node)) return "builtin";
|
|
115
|
+
if (isPackageScope(node)) return "package";
|
|
116
|
+
if (isDataNode(node)) return node.kind;
|
|
117
|
+
if (callsItself(graph, node)) return "recursive";
|
|
118
|
+
if (isExternal(node) && node.kind === "func") return "external_func";
|
|
119
|
+
if (interfaceMethods(graph).has(node.id)) return "interface_method";
|
|
120
|
+
return ((_a = UIR_KINDS.get(node.kind)) == null ? void 0 : _a.glyph) ?? "symbol";
|
|
121
|
+
}
|
|
122
|
+
function uirKind(graph, node) {
|
|
123
|
+
var _a;
|
|
124
|
+
if (node.unresolved) return "unresolved call";
|
|
125
|
+
const kind = interfaceMethods(graph).has(node.id) ? "interface method" : ((_a = UIR_KINDS.get(node.kind)) == null ? void 0 : _a.words) ?? DATA_KIND_WORDS[node.kind] ?? node.kind.replaceAll("_", " ");
|
|
126
|
+
return [isExternal(node) ? "external" : "", callsItself(graph, node) ? "recursive" : "", kind].filter(Boolean).join(" ");
|
|
127
|
+
}
|
|
128
|
+
function uirStatus(node) {
|
|
129
|
+
if (node.unresolved) return "Unresolved: the index has no target for this call";
|
|
130
|
+
if (isBuiltin(node)) return "Builtin: no source";
|
|
131
|
+
if (isExternal(node)) return "External: declared outside the indexed snapshots";
|
|
132
|
+
if (node.location) return "Indexed";
|
|
133
|
+
return isDataNode(node) ? dataNodeStatus(node) : "Package scope: calls made outside any declaration";
|
|
134
|
+
}
|
|
135
|
+
const UIR_CALL_GRAPH_VOCABULARY = {
|
|
136
|
+
glyphs: [
|
|
137
|
+
{ id: "func", name: "function", icon: UiFunction.UiFunction },
|
|
138
|
+
{ id: "method", name: "method", icon: UiMethod.UiMethod },
|
|
139
|
+
{ id: "interface_method", name: "interface method", icon: UiInterface.UiInterface },
|
|
140
|
+
{ id: "recursive", name: "calls itself", icon: UiMethod11.UiMethod11, darkIcon: UiMethod11.UiMethod11Dark },
|
|
141
|
+
{ id: "external_func", name: "external function", icon: UiFunction1.UiFunction1, darkIcon: UiFunction1.UiFunction1Dark },
|
|
142
|
+
{ id: "builtin", name: "builtin", icon: UiFunctionSquare.UiFunctionSquare },
|
|
143
|
+
{ id: "type", name: "type", icon: UiTypeParameter.UiTypeParameter },
|
|
144
|
+
{ id: "field", name: "field", icon: UiField.UiField },
|
|
145
|
+
{ id: "var", name: "variable", icon: UiVariable.UiVariable },
|
|
146
|
+
{ id: "const", name: "constant", icon: UiConstant.UiConstant },
|
|
147
|
+
{ id: "package", name: "package scope", icon: UiPackage.UiPackage },
|
|
148
|
+
// uir's `field` is already a glyph of its own: a struct field is data too.
|
|
149
|
+
...CALL_GRAPH_DATA_GLYPHS.filter((glyph) => glyph.id !== "field"),
|
|
150
|
+
{ id: "unresolved", name: "unresolved call", icon: UiUnknown.UiUnknown },
|
|
151
|
+
{ id: "symbol", name: "other symbol", icon: UiSymbol.UiSymbol, darkIcon: UiSymbol.UiSymbolDark }
|
|
152
|
+
],
|
|
153
|
+
glyphOf: uirGlyph,
|
|
154
|
+
kindOf: uirKind,
|
|
155
|
+
hasSource: (node) => Boolean(node.location),
|
|
156
|
+
canRoot: (node) => Boolean(node.location) || isDataNode(node),
|
|
157
|
+
isData: isDataNode,
|
|
158
|
+
muted: (node) => Boolean(node.unresolved) || isBuiltin(node) || isExternal(node),
|
|
159
|
+
status: uirStatus,
|
|
160
|
+
backing: dataNodeBacking,
|
|
161
|
+
group: { noun: "package", plural: "packages", icon: UiPackage.UiPackage, patternHint: "example.com/module/..." }
|
|
162
|
+
};
|
|
163
|
+
exports.CALL_GRAPH_DATA_GLYPHS = CALL_GRAPH_DATA_GLYPHS;
|
|
164
|
+
exports.DATA_KIND_WORDS = DATA_KIND_WORDS;
|
|
165
|
+
exports.UIR_CALL_GRAPH_VOCABULARY = UIR_CALL_GRAPH_VOCABULARY;
|
|
166
|
+
exports.callsItself = callsItself;
|
|
167
|
+
exports.dataNodeBacking = dataNodeBacking;
|
|
168
|
+
exports.dataNodeStatus = dataNodeStatus;
|
|
169
|
+
exports.interfaceMethods = interfaceMethods;
|
|
170
|
+
exports.isBuiltin = isBuiltin;
|
|
171
|
+
exports.isDataNode = isDataNode;
|
|
172
|
+
exports.isExternal = isExternal;
|
|
173
|
+
exports.nodeTitle = nodeTitle;
|
|
174
|
+
exports.requireGlyph = requireGlyph;
|
|
175
|
+
exports.siteKey = siteKey;
|
|
176
|
+
exports.usedGlyphs = usedGlyphs;
|
|
177
|
+
//# sourceMappingURL=call-graph-vocabulary.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-graph-vocabulary.cjs","sources":["../../../src/data/call-graph/call-graph-vocabulary.ts"],"sourcesContent":["// What a node kind means and how it is drawn. A host whose source names its own kinds (OIPA's\n// transactions, copybooks and functions) passes its own vocabulary; the default is the one uir's\n// `graph.Build` reports without a Theme: uir node types, a builtin, a package scope and an index\n// location for every node with a source.\nimport {\n UiConstant,\n UiField,\n UiFunction,\n UiFunction1,\n UiFunction1Dark,\n UiFunctionSquare,\n UiInterface,\n UiMethod,\n UiMethod11,\n UiMethod11Dark,\n UiPackage,\n UiSqlColumn,\n UiSqlStoredProc,\n UiSqlTable,\n UiSymbol,\n UiSymbolDark,\n UiTableProperties,\n UiTypeParameter,\n UiUnknown,\n UiVariable,\n type IconComponent,\n} from \"../../icons\";\nimport type { CallGraph, CallGraphNode } from \"./types\";\n\nexport interface CallGraphGlyph {\n id: string;\n /** The legend's name for it. */\n name: string;\n icon: IconComponent;\n /** Drawn instead of `icon` in the dark theme, for coloured artwork. */\n darkIcon?: IconComponent;\n}\n\nexport interface CallGraphVocabulary {\n /** Every glyph the vocabulary draws, in legend order. */\n glyphs: readonly CallGraphGlyph[];\n /** The id of the one glyph a node shows. */\n glyphOf(graph: CallGraph, node: CallGraphNode): string;\n /** What the node is, in words: `method`, `external function`, `copybook`. */\n kindOf(graph: CallGraph, node: CallGraphNode): string;\n /** The node has a body the source walks: it can be expanded and opened. */\n hasSource(node: CallGraphNode): boolean;\n /** The graph can be drawn around the node: Focus is offered for it, with or without a source. */\n canRoot(node: CallGraphNode): boolean;\n /** A table, column, procedure, entity or field: its details count readers and writers. */\n isData(node: CallGraphNode): boolean;\n /** Drawn dimmed: the node leads nowhere further. */\n muted(node: CallGraphNode): boolean;\n /** The node's status line in its details. */\n status(node: CallGraphNode): string;\n /** The node a data node stands for, such as the column behind a field, offered as a Focus link. */\n backing?(node: CallGraphNode): { id: string; label: string } | undefined;\n /** What a group is, and the icon its box caption shows. */\n group: { noun: string; plural: string; icon: IconComponent; patternHint: string };\n}\n\n/** The glyph with that id, failing on one the vocabulary does not list. */\nexport function requireGlyph(vocabulary: CallGraphVocabulary, id: string): CallGraphGlyph {\n const glyph = vocabulary.glyphs.find((candidate) => candidate.id === id);\n if (!glyph) throw new Error(`call graph: the vocabulary has no glyph \"${id}\"`);\n return glyph;\n}\n\n/** The glyphs the graph's nodes use, once each, in legend order. */\nexport function usedGlyphs(graph: CallGraph, vocabulary: CallGraphVocabulary): CallGraphGlyph[] {\n const used = new Set(graph.nodes.map((node) => vocabulary.glyphOf(graph, node)));\n return vocabulary.glyphs.filter((glyph) => used.has(glyph.id));\n}\n\n/** The node's tooltip: its kind, its label and its group's full label. */\nexport function nodeTitle(graph: CallGraph, node: CallGraphNode, vocabulary: CallGraphVocabulary): string {\n const group = graph.groups?.find((candidate) => candidate.id === node.group)?.label ?? node.group;\n return `${vocabulary.kindOf(graph, node)} ${node.label}${group ? ` in ${group}` : \"\"}`;\n}\n\nexport function callsItself(graph: CallGraph, node: CallGraphNode): boolean {\n return graph.edges.some((edge) => edge.from === node.id && edge.to === node.id);\n}\n\nexport function siteKey(site: { path?: string; line?: number; column?: number }): string {\n return `${site.path}:${site.line}:${site.column}`;\n}\n\n// uir node types that have a glyph of their own, and the words for each.\nconst UIR_KINDS = new Map<string, { glyph: string; words: string }>([\n [\"func\", { glyph: \"func\", words: \"function\" }],\n [\"method\", { glyph: \"method\", words: \"method\" }],\n [\"builtin\", { glyph: \"builtin\", words: \"builtin\" }],\n [\"type\", { glyph: \"type\", words: \"type\" }],\n [\"field\", { glyph: \"field\", words: \"field\" }],\n [\"var\", { glyph: \"var\", words: \"variable\" }],\n [\"const\", { glyph: \"const\", words: \"constant\" }],\n [\"package\", { glyph: \"package\", words: \"package scope\" }],\n]);\n\n// Data access, as the graph's data model names it: `table:AsPolicy`, `column:AsPolicy.STATUSCODE`,\n// `procedure:Update_ClassGroup`, `entity:Policy` and `field:Policy.StatusCode`, a field carrying\n// `column` (its `x-oipa-column`) or `storage` (the table a dynamic field is kept in).\n\nexport const DATA_KIND_WORDS: Readonly<Record<string, string>> = {\n table: \"table\",\n column: \"column\",\n procedure: \"stored procedure\",\n entity: \"entity\",\n field: \"field\",\n};\n\nexport const CALL_GRAPH_DATA_GLYPHS: readonly CallGraphGlyph[] = [\n { id: \"table\", name: \"table\", icon: UiSqlTable },\n { id: \"column\", name: \"column\", icon: UiSqlColumn },\n { id: \"procedure\", name: \"stored procedure\", icon: UiSqlStoredProc },\n { id: \"entity\", name: \"entity\", icon: UiTableProperties },\n { id: \"field\", name: \"field\", icon: UiField },\n];\n\nexport function isDataNode(node: CallGraphNode): boolean {\n return Object.hasOwn(DATA_KIND_WORDS, node.kind);\n}\n\n/** The data node's name: its id after `<kind>:`, else its label. */\nfunction dataName(node: CallGraphNode): string {\n const prefix = `${node.kind}:`;\n return node.id.startsWith(prefix) ? node.id.slice(prefix.length) : node.label;\n}\n\nexport function dataNodeStatus(node: CallGraphNode): string {\n const name = dataName(node);\n switch (node.kind) {\n case \"table\": return `Table ${name}`;\n case \"column\": return `Column ${name}`;\n case \"procedure\": return `Stored procedure ${name}`;\n case \"entity\": return `${name} fields`;\n }\n const entity = name.includes(\".\") ? name.slice(0, name.indexOf(\".\")) : (node.group ?? \"\");\n const { column, storage } = node.properties ?? {};\n if (column) return `${entity} field → ${column}`;\n if (storage) return `${entity} field, dynamic, stored in ${storage}`;\n return `${entity} field`;\n}\n\n/** The column behind a field, by its `column` property. */\nexport function dataNodeBacking(node: CallGraphNode): { id: string; label: string } | undefined {\n const column = node.kind === \"field\" ? node.properties?.column : undefined;\n return column ? { id: `column:${column}`, label: column } : undefined;\n}\n\nexport function isBuiltin(node: CallGraphNode): boolean {\n return node.kind === \"builtin\";\n}\n\n/** The node standing for the calls a package makes outside any declaration. */\nfunction isPackageScope(node: CallGraphNode): boolean {\n return node.kind === \"package\";\n}\n\n/** A symbol declared outside the indexed snapshots: it has no source, so it cannot be opened or expanded. */\nexport function isExternal(node: CallGraphNode): boolean {\n return !node.location && !node.unresolved && !isBuiltin(node) && !isPackageScope(node) && !isDataNode(node);\n}\n\n/**\n * The index has no kind for an interface method: it is a `method`. It shows in the graph as the target\n * of a call whose site also carries a dispatch edge from the same caller, because the source adds that\n * dispatch edge to each implementation of the interface method called there.\n */\nexport function interfaceMethods(graph: CallGraph): Set<string> {\n const dispatched = new Set(\n graph.edges.filter((edge) => edge.type === \"dispatch\").flatMap((edge) => edge.sites.map((site) => `${edge.from} ${siteKey(site)}`)),\n );\n return new Set(\n graph.edges\n .filter((edge) => edge.type === \"call\" && edge.sites.some((site) => dispatched.has(`${edge.from} ${siteKey(site)}`)))\n .map((edge) => edge.to),\n );\n}\n\n/**\n * The one glyph a node shows. An unresolved call, a builtin and a package scope are what they are;\n * after those, a symbol that calls itself, an external function and an interface method outrank the\n * plain kind. An external method keeps the method glyph: its dimmed box already says it has no source.\n */\nfunction uirGlyph(graph: CallGraph, node: CallGraphNode): string {\n if (node.unresolved) return \"unresolved\";\n if (isBuiltin(node)) return \"builtin\";\n if (isPackageScope(node)) return \"package\";\n if (isDataNode(node)) return node.kind;\n if (callsItself(graph, node)) return \"recursive\";\n if (isExternal(node) && node.kind === \"func\") return \"external_func\";\n if (interfaceMethods(graph).has(node.id)) return \"interface_method\";\n return UIR_KINDS.get(node.kind)?.glyph ?? \"symbol\";\n}\n\nfunction uirKind(graph: CallGraph, node: CallGraphNode): string {\n if (node.unresolved) return \"unresolved call\";\n const kind = interfaceMethods(graph).has(node.id) ? \"interface method\" : (UIR_KINDS.get(node.kind)?.words ?? DATA_KIND_WORDS[node.kind] ?? node.kind.replaceAll(\"_\", \" \"));\n return [isExternal(node) ? \"external\" : \"\", callsItself(graph, node) ? \"recursive\" : \"\", kind].filter(Boolean).join(\" \");\n}\n\nfunction uirStatus(node: CallGraphNode): string {\n if (node.unresolved) return \"Unresolved: the index has no target for this call\";\n if (isBuiltin(node)) return \"Builtin: no source\";\n if (isExternal(node)) return \"External: declared outside the indexed snapshots\";\n if (node.location) return \"Indexed\";\n return isDataNode(node) ? dataNodeStatus(node) : \"Package scope: calls made outside any declaration\";\n}\n\nexport const UIR_CALL_GRAPH_VOCABULARY: CallGraphVocabulary = {\n glyphs: [\n { id: \"func\", name: \"function\", icon: UiFunction },\n { id: \"method\", name: \"method\", icon: UiMethod },\n { id: \"interface_method\", name: \"interface method\", icon: UiInterface },\n { id: \"recursive\", name: \"calls itself\", icon: UiMethod11, darkIcon: UiMethod11Dark },\n { id: \"external_func\", name: \"external function\", icon: UiFunction1, darkIcon: UiFunction1Dark },\n { id: \"builtin\", name: \"builtin\", icon: UiFunctionSquare },\n { id: \"type\", name: \"type\", icon: UiTypeParameter },\n { id: \"field\", name: \"field\", icon: UiField },\n { id: \"var\", name: \"variable\", icon: UiVariable },\n { id: \"const\", name: \"constant\", icon: UiConstant },\n { id: \"package\", name: \"package scope\", icon: UiPackage },\n // uir's `field` is already a glyph of its own: a struct field is data too.\n ...CALL_GRAPH_DATA_GLYPHS.filter((glyph) => glyph.id !== \"field\"),\n { id: \"unresolved\", name: \"unresolved call\", icon: UiUnknown },\n { id: \"symbol\", name: \"other symbol\", icon: UiSymbol, darkIcon: UiSymbolDark },\n ],\n glyphOf: uirGlyph,\n kindOf: uirKind,\n hasSource: (node) => Boolean(node.location),\n canRoot: (node) => Boolean(node.location) || isDataNode(node),\n isData: isDataNode,\n muted: (node) => Boolean(node.unresolved) || isBuiltin(node) || isExternal(node),\n status: uirStatus,\n backing: dataNodeBacking,\n group: { noun: \"package\", plural: \"packages\", icon: UiPackage, patternHint: \"example.com/module/...\" },\n};\n"],"names":["UiSqlTable","UiSqlColumn","UiSqlStoredProc","UiTableProperties","UiField","UiFunction","UiMethod","UiInterface","UiMethod11","UiMethod11Dark","UiFunction1","UiFunction1Dark","UiFunctionSquare","UiTypeParameter","UiVariable","UiConstant","UiPackage","UiUnknown","UiSymbol","UiSymbolDark"],"mappings":"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"}
|