dbwatcher 1.1.2 → 1.1.4
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.
- checksums.yaml +4 -4
- data/app/assets/config/dbwatcher_manifest.js +1 -0
- data/app/assets/javascripts/dbwatcher/components/changes_table_hybrid.js +184 -97
- data/app/assets/javascripts/dbwatcher/components/timeline.js +211 -0
- data/app/assets/javascripts/dbwatcher/dbwatcher.js +5 -0
- data/app/assets/stylesheets/dbwatcher/application.css +298 -1
- data/app/assets/stylesheets/dbwatcher/application.scss +1 -0
- data/app/assets/stylesheets/dbwatcher/components/_timeline.scss +326 -0
- data/app/controllers/dbwatcher/api/v1/sessions_controller.rb +27 -17
- data/app/controllers/dbwatcher/sessions_controller.rb +1 -1
- data/app/views/dbwatcher/sessions/_layout.html.erb +5 -2
- data/app/views/dbwatcher/sessions/_summary.html.erb +1 -1
- data/app/views/dbwatcher/sessions/{_changes.html.erb → _tables.html.erb} +84 -5
- data/app/views/dbwatcher/sessions/_timeline.html.erb +260 -0
- data/app/views/dbwatcher/sessions/show.html.erb +3 -1
- data/app/views/layouts/dbwatcher/application.html.erb +1 -0
- data/config/routes.rb +2 -1
- data/lib/dbwatcher/configuration.rb +11 -0
- data/lib/dbwatcher/logging.rb +23 -1
- data/lib/dbwatcher/services/analyzers/table_summary_builder.rb +102 -1
- data/lib/dbwatcher/services/api/{changes_data_service.rb → tables_data_service.rb} +6 -6
- data/lib/dbwatcher/services/diagram_analyzers/inferred_relationship_analyzer.rb +62 -36
- data/lib/dbwatcher/services/diagram_generator.rb +35 -69
- data/lib/dbwatcher/services/diagram_strategies/base_diagram_strategy.rb +23 -9
- data/lib/dbwatcher/services/diagram_strategies/class_diagram_strategy.rb +16 -22
- data/lib/dbwatcher/services/diagram_strategies/diagram_strategy_helpers.rb +33 -0
- data/lib/dbwatcher/services/diagram_strategies/erd_diagram_strategy.rb +20 -25
- data/lib/dbwatcher/services/diagram_strategies/flowchart_diagram_strategy.rb +20 -25
- data/lib/dbwatcher/services/diagram_strategies/standard_diagram_strategy.rb +80 -0
- data/lib/dbwatcher/services/diagram_system.rb +14 -1
- data/lib/dbwatcher/services/mermaid_syntax/base_builder.rb +2 -0
- data/lib/dbwatcher/services/mermaid_syntax_builder.rb +10 -8
- data/lib/dbwatcher/services/timeline_data_service/enhancement_utilities.rb +100 -0
- data/lib/dbwatcher/services/timeline_data_service/entry_builder.rb +125 -0
- data/lib/dbwatcher/services/timeline_data_service/metadata_builder.rb +93 -0
- data/lib/dbwatcher/services/timeline_data_service.rb +130 -0
- data/lib/dbwatcher/storage/api/concerns/table_analyzer.rb +1 -1
- data/lib/dbwatcher/version.rb +1 -1
- data/lib/dbwatcher.rb +1 -1
- metadata +13 -4
@@ -5,81 +5,58 @@ require_relative "diagram_type_registry"
|
|
5
5
|
|
6
6
|
module Dbwatcher
|
7
7
|
module Services
|
8
|
-
#
|
8
|
+
# Service for generating diagrams from session data
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
10
|
+
# Coordinates the process of generating diagrams by:
|
11
|
+
# 1. Loading session data
|
12
|
+
# 2. Using appropriate analyzers to extract relationships
|
13
|
+
# 3. Applying diagram generation strategies
|
12
14
|
#
|
13
15
|
# @example
|
14
|
-
# generator = DiagramGenerator.new(session_id,
|
16
|
+
# generator = DiagramGenerator.new(session_id: "abc123", diagram_type: "database_tables")
|
15
17
|
# result = generator.call
|
16
|
-
# # => { content: "erDiagram\n
|
17
|
-
class DiagramGenerator
|
18
|
-
|
18
|
+
# # => { success: true, content: "erDiagram\n...", type: "erDiagram" }
|
19
|
+
class DiagramGenerator
|
20
|
+
include Dbwatcher::Logging
|
19
21
|
|
20
|
-
# Initialize with
|
22
|
+
# Initialize generator with options
|
21
23
|
#
|
22
|
-
# @param session_id [String] session
|
24
|
+
# @param session_id [String] session ID to analyze
|
23
25
|
# @param diagram_type [String] type of diagram to generate
|
24
|
-
# @param
|
25
|
-
|
26
|
-
# @option dependencies [DiagramErrorHandler] :error_handler error handler
|
27
|
-
# @option dependencies [Logger] :logger logger instance
|
28
|
-
def initialize(session_id, diagram_type = "database_tables", dependencies = {})
|
26
|
+
# @param options [Hash] additional options
|
27
|
+
def initialize(session_id:, diagram_type:, options: {})
|
29
28
|
@session_id = session_id
|
30
29
|
@diagram_type = diagram_type
|
31
|
-
@
|
32
|
-
@
|
33
|
-
@logger =
|
34
|
-
super()
|
30
|
+
@options = options
|
31
|
+
@registry = options[:registry] || DiagramTypeRegistry.new
|
32
|
+
@logger = options[:logger] || Rails.logger
|
35
33
|
end
|
36
34
|
|
37
|
-
# Generate diagram
|
35
|
+
# Generate diagram
|
38
36
|
#
|
39
|
-
# @return [Hash] diagram
|
37
|
+
# @return [Hash] diagram generation result
|
40
38
|
def call
|
41
|
-
|
42
|
-
start_time = Time.now
|
39
|
+
log_info("Generating diagram of type #{@diagram_type} for session #{@session_id}")
|
43
40
|
|
44
|
-
|
45
|
-
|
46
|
-
log_completion(start_time, result)
|
47
|
-
result
|
48
|
-
rescue StandardError => e
|
49
|
-
@error_handler.handle_generation_error(e, error_context)
|
50
|
-
end
|
51
|
-
end
|
41
|
+
start_time = Time.now
|
42
|
+
result = generate_diagram
|
52
43
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
44
|
+
duration_ms = ((Time.now - start_time) * 1000).round(2)
|
45
|
+
log_info("Diagram generation completed in #{duration_ms}ms", {
|
46
|
+
session_id: @session_id,
|
47
|
+
diagram_type: @diagram_type,
|
48
|
+
success: result[:success]
|
49
|
+
})
|
59
50
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
DiagramTypeRegistry.new.available_types_with_metadata
|
51
|
+
result
|
52
|
+
rescue StandardError => e
|
53
|
+
log_error("Diagram generation failed: #{e.message}", error_context)
|
54
|
+
error_result("Diagram generation failed: #{e.message}")
|
65
55
|
end
|
66
56
|
|
67
57
|
private
|
68
58
|
|
69
|
-
#
|
70
|
-
#
|
71
|
-
# @return [Logger] default logger instance
|
72
|
-
def default_logger
|
73
|
-
# Use Rails logger if available, otherwise create a simple logger
|
74
|
-
if defined?(Rails) && Rails.respond_to?(:logger)
|
75
|
-
Rails.logger
|
76
|
-
else
|
77
|
-
require "logger"
|
78
|
-
Logger.new($stdout)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Generate diagram using standardized analyzer-to-strategy flow
|
59
|
+
# Generate diagram based on configuration
|
83
60
|
#
|
84
61
|
# @return [Hash] diagram generation result
|
85
62
|
def generate_diagram
|
@@ -96,8 +73,8 @@ module Dbwatcher
|
|
96
73
|
analyzer = @registry.create_analyzer(@diagram_type, session)
|
97
74
|
dataset = analyzer.call
|
98
75
|
|
99
|
-
|
100
|
-
|
76
|
+
log_debug("Generated dataset with #{dataset.entities.size} entities and " \
|
77
|
+
"#{dataset.relationships.size} relationships")
|
101
78
|
|
102
79
|
# Create strategy and generate diagram from dataset
|
103
80
|
strategy = @registry.create_strategy(@diagram_type)
|
@@ -110,7 +87,7 @@ module Dbwatcher
|
|
110
87
|
def load_session
|
111
88
|
Dbwatcher::Storage.sessions.find(@session_id)
|
112
89
|
rescue StandardError => e
|
113
|
-
|
90
|
+
log_warn("Could not load session #{@session_id}: #{e.message}")
|
114
91
|
nil
|
115
92
|
end
|
116
93
|
|
@@ -138,17 +115,6 @@ module Dbwatcher
|
|
138
115
|
generated_at: Time.now.iso8601
|
139
116
|
}
|
140
117
|
end
|
141
|
-
|
142
|
-
# Log generation completion
|
143
|
-
#
|
144
|
-
# @param start_time [Time] operation start time
|
145
|
-
# @param result [Hash] generation result
|
146
|
-
def log_completion(start_time, result)
|
147
|
-
duration = Time.now - start_time
|
148
|
-
success = result[:success] || false
|
149
|
-
@logger.info("Diagram generation completed for session #{@session_id} type #{@diagram_type} " \
|
150
|
-
"in #{(duration * 1000).round(2)}ms - Success: #{success}")
|
151
|
-
end
|
152
118
|
end
|
153
119
|
end
|
154
120
|
end
|
@@ -8,6 +8,8 @@ module Dbwatcher
|
|
8
8
|
# Defines the common interface and shared behavior for all diagram generation
|
9
9
|
# strategies. Subclasses must implement the render_diagram method.
|
10
10
|
class BaseDiagramStrategy
|
11
|
+
include Dbwatcher::Logging
|
12
|
+
|
11
13
|
attr_reader :syntax_builder, :logger
|
12
14
|
|
13
15
|
# Initialize strategy with dependencies
|
@@ -25,8 +27,8 @@ module Dbwatcher
|
|
25
27
|
# @param dataset [Dataset] standardized dataset
|
26
28
|
# @return [Hash] diagram generation result
|
27
29
|
def generate_from_dataset(dataset)
|
28
|
-
|
29
|
-
|
30
|
+
log_info("Generating diagram from dataset with #{dataset.entities.size} entities and " \
|
31
|
+
"#{dataset.relationships.size} relationships")
|
30
32
|
start_time = Time.current
|
31
33
|
|
32
34
|
begin
|
@@ -40,7 +42,7 @@ module Dbwatcher
|
|
40
42
|
|
41
43
|
result
|
42
44
|
rescue StandardError => e
|
43
|
-
|
45
|
+
log_error("Diagram generation failed: #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}")
|
44
46
|
error_response("Diagram generation failed: #{e.message}")
|
45
47
|
end
|
46
48
|
end
|
@@ -59,13 +61,25 @@ module Dbwatcher
|
|
59
61
|
|
60
62
|
protected
|
61
63
|
|
62
|
-
# Render diagram from dataset (
|
64
|
+
# Render diagram from dataset (template method)
|
63
65
|
#
|
64
66
|
# @param dataset [Dataset] standardized dataset
|
65
67
|
# @return [Hash] diagram generation result
|
66
|
-
# @raise [NotImplementedError] if not implemented by subclass
|
67
68
|
def render_diagram(dataset)
|
68
|
-
|
69
|
+
log_debug("Rendering #{mermaid_diagram_type} diagram from dataset with " \
|
70
|
+
"#{dataset.entities.size} entities and #{dataset.relationships.size} relationships")
|
71
|
+
|
72
|
+
# Generate diagram content directly from dataset
|
73
|
+
content = generate_diagram_content(dataset)
|
74
|
+
success_response(content, mermaid_diagram_type)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Generate diagram content based on dataset (to be implemented by subclasses)
|
78
|
+
#
|
79
|
+
# @param dataset [Dataset] standardized dataset
|
80
|
+
# @return [String] diagram content
|
81
|
+
def generate_diagram_content(dataset)
|
82
|
+
raise NotImplementedError, "Subclasses must implement generate_diagram_content method"
|
69
83
|
end
|
70
84
|
|
71
85
|
# Build empty diagram with message
|
@@ -118,9 +132,9 @@ module Dbwatcher
|
|
118
132
|
# @param operation [String] operation name
|
119
133
|
# @param duration [Float] operation duration in seconds
|
120
134
|
# @param context [Hash] additional context
|
121
|
-
def log_operation_completion(operation, duration,
|
122
|
-
|
123
|
-
|
135
|
+
def log_operation_completion(operation, duration, context = {})
|
136
|
+
log_info("Strategy operation completed: #{operation} by #{self.class.name} " \
|
137
|
+
"in #{(duration * 1000).round(2)}ms", context)
|
124
138
|
end
|
125
139
|
|
126
140
|
# Create default syntax builder
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "standard_diagram_strategy"
|
4
|
+
|
3
5
|
module Dbwatcher
|
4
6
|
module Services
|
5
7
|
module DiagramStrategies
|
@@ -7,31 +9,10 @@ module Dbwatcher
|
|
7
9
|
#
|
8
10
|
# Handles class diagram generation by converting dataset entities and relationships
|
9
11
|
# to Mermaid class diagram syntax.
|
10
|
-
class ClassDiagramStrategy <
|
11
|
-
protected
|
12
|
-
|
13
|
-
# Render class diagram from standardized dataset
|
14
|
-
#
|
15
|
-
# @param dataset [Dataset] standardized dataset
|
16
|
-
# @return [Hash] diagram generation result
|
17
|
-
def render_diagram(dataset)
|
18
|
-
@logger.debug "Rendering class diagram from dataset with #{dataset.entities.size} entities and " \
|
19
|
-
"#{dataset.relationships.size} relationships"
|
20
|
-
|
21
|
-
# Generate diagram content directly from dataset
|
22
|
-
content = if dataset.relationships.empty? && dataset.entities.empty?
|
23
|
-
@syntax_builder.build_empty_class_diagram("No model associations or entities found")
|
24
|
-
else
|
25
|
-
@syntax_builder.build_class_diagram_from_dataset(dataset)
|
26
|
-
end
|
27
|
-
|
28
|
-
success_response(content, "classDiagram")
|
29
|
-
end
|
30
|
-
|
12
|
+
class ClassDiagramStrategy < StandardDiagramStrategy
|
31
13
|
private
|
32
14
|
|
33
15
|
# Strategy metadata methods
|
34
|
-
|
35
16
|
def strategy_name
|
36
17
|
"Model Associations (Class Diagram)"
|
37
18
|
end
|
@@ -43,6 +24,19 @@ module Dbwatcher
|
|
43
24
|
def mermaid_diagram_type
|
44
25
|
"classDiagram"
|
45
26
|
end
|
27
|
+
|
28
|
+
# Diagram generation configuration
|
29
|
+
def empty_diagram_method
|
30
|
+
:build_empty_class_diagram
|
31
|
+
end
|
32
|
+
|
33
|
+
def empty_diagram_message
|
34
|
+
"No model associations or entities found"
|
35
|
+
end
|
36
|
+
|
37
|
+
def full_diagram_method
|
38
|
+
:build_class_diagram_from_dataset
|
39
|
+
end
|
46
40
|
end
|
47
41
|
end
|
48
42
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dbwatcher
|
4
|
+
module Services
|
5
|
+
module DiagramStrategies
|
6
|
+
# Helper module for diagram strategies
|
7
|
+
#
|
8
|
+
# Provides common utility methods for diagram strategies to reduce code duplication.
|
9
|
+
# These methods handle common patterns in diagram generation.
|
10
|
+
module DiagramStrategyHelpers
|
11
|
+
# Generate diagram content with empty state handling
|
12
|
+
#
|
13
|
+
# @param dataset [Dataset] standardized dataset
|
14
|
+
# @param options [Hash] options for diagram generation
|
15
|
+
# @option options [Symbol] :empty_method method to call for empty diagram
|
16
|
+
# @option options [String] :empty_message message for empty diagram
|
17
|
+
# @option options [Symbol] :empty_entities_method method to call for diagram with only entities
|
18
|
+
# @option options [Symbol] :full_diagram_method method to call for complete diagram
|
19
|
+
# @return [String] diagram content
|
20
|
+
def generate_standard_diagram_content(dataset, options)
|
21
|
+
if dataset.relationships.empty? && dataset.entities.empty?
|
22
|
+
@syntax_builder.send(options[:empty_method], options[:empty_message])
|
23
|
+
elsif dataset.relationships.empty? && options[:empty_entities_method]
|
24
|
+
# Show isolated entities if no relationships but entities exist
|
25
|
+
@syntax_builder.send(options[:empty_entities_method], dataset.entities.values)
|
26
|
+
else
|
27
|
+
@syntax_builder.send(options[:full_diagram_method], dataset)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "standard_diagram_strategy"
|
4
|
+
|
3
5
|
module Dbwatcher
|
4
6
|
module Services
|
5
7
|
module DiagramStrategies
|
@@ -7,34 +9,10 @@ module Dbwatcher
|
|
7
9
|
#
|
8
10
|
# Handles ERD diagram generation by converting dataset entities and relationships
|
9
11
|
# to Mermaid ERD syntax.
|
10
|
-
class ErdDiagramStrategy <
|
11
|
-
protected
|
12
|
-
|
13
|
-
# Render ERD diagram from standardized dataset
|
14
|
-
#
|
15
|
-
# @param dataset [Dataset] standardized dataset
|
16
|
-
# @return [Hash] diagram generation result
|
17
|
-
def render_diagram(dataset)
|
18
|
-
@logger.debug "Rendering ERD diagram from dataset with #{dataset.entities.size} entities and " \
|
19
|
-
"#{dataset.relationships.size} relationships"
|
20
|
-
|
21
|
-
# Generate diagram content directly from dataset
|
22
|
-
content = if dataset.relationships.empty? && dataset.entities.empty?
|
23
|
-
@syntax_builder.build_empty_erd("No database relationships or tables found")
|
24
|
-
elsif dataset.relationships.empty?
|
25
|
-
# Show isolated tables if no relationships but entities exist
|
26
|
-
@syntax_builder.build_erd_diagram_with_tables(dataset.entities.values)
|
27
|
-
else
|
28
|
-
@syntax_builder.build_erd_diagram_from_dataset(dataset)
|
29
|
-
end
|
30
|
-
|
31
|
-
success_response(content, "erDiagram")
|
32
|
-
end
|
33
|
-
|
12
|
+
class ErdDiagramStrategy < StandardDiagramStrategy
|
34
13
|
private
|
35
14
|
|
36
15
|
# Strategy metadata methods
|
37
|
-
|
38
16
|
def strategy_name
|
39
17
|
"Database Schema (ERD)"
|
40
18
|
end
|
@@ -46,6 +24,23 @@ module Dbwatcher
|
|
46
24
|
def mermaid_diagram_type
|
47
25
|
"erDiagram"
|
48
26
|
end
|
27
|
+
|
28
|
+
# Diagram generation configuration
|
29
|
+
def empty_diagram_method
|
30
|
+
:build_empty_erd
|
31
|
+
end
|
32
|
+
|
33
|
+
def empty_diagram_message
|
34
|
+
"No database relationships or tables found"
|
35
|
+
end
|
36
|
+
|
37
|
+
def empty_entities_method
|
38
|
+
:build_erd_diagram_with_tables
|
39
|
+
end
|
40
|
+
|
41
|
+
def full_diagram_method
|
42
|
+
:build_erd_diagram_from_dataset
|
43
|
+
end
|
49
44
|
end
|
50
45
|
end
|
51
46
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "standard_diagram_strategy"
|
4
|
+
|
3
5
|
module Dbwatcher
|
4
6
|
module Services
|
5
7
|
module DiagramStrategies
|
@@ -7,34 +9,10 @@ module Dbwatcher
|
|
7
9
|
#
|
8
10
|
# Handles flowchart diagram generation by converting dataset entities and relationships
|
9
11
|
# to Mermaid flowchart syntax.
|
10
|
-
class FlowchartDiagramStrategy <
|
11
|
-
protected
|
12
|
-
|
13
|
-
# Render flowchart diagram from standardized dataset
|
14
|
-
#
|
15
|
-
# @param dataset [Dataset] standardized dataset
|
16
|
-
# @return [Hash] diagram generation result
|
17
|
-
def render_diagram(dataset)
|
18
|
-
@logger.debug "Rendering flowchart diagram from dataset with #{dataset.entities.size} entities and " \
|
19
|
-
"#{dataset.relationships.size} relationships"
|
20
|
-
|
21
|
-
# Generate diagram content directly from dataset
|
22
|
-
content = if dataset.relationships.empty? && dataset.entities.empty?
|
23
|
-
@syntax_builder.build_empty_flowchart("No model associations or entities found")
|
24
|
-
elsif dataset.relationships.empty?
|
25
|
-
# Show isolated nodes if no relationships but entities exist
|
26
|
-
@syntax_builder.build_flowchart_with_nodes(dataset.entities.values)
|
27
|
-
else
|
28
|
-
@syntax_builder.build_flowchart_diagram_from_dataset(dataset)
|
29
|
-
end
|
30
|
-
|
31
|
-
success_response(content, "flowchart")
|
32
|
-
end
|
33
|
-
|
12
|
+
class FlowchartDiagramStrategy < StandardDiagramStrategy
|
34
13
|
private
|
35
14
|
|
36
15
|
# Strategy metadata methods
|
37
|
-
|
38
16
|
def strategy_name
|
39
17
|
"Model Associations"
|
40
18
|
end
|
@@ -46,6 +24,23 @@ module Dbwatcher
|
|
46
24
|
def mermaid_diagram_type
|
47
25
|
"flowchart"
|
48
26
|
end
|
27
|
+
|
28
|
+
# Diagram generation configuration
|
29
|
+
def empty_diagram_method
|
30
|
+
:build_empty_flowchart
|
31
|
+
end
|
32
|
+
|
33
|
+
def empty_diagram_message
|
34
|
+
"No model associations or entities found"
|
35
|
+
end
|
36
|
+
|
37
|
+
def empty_entities_method
|
38
|
+
:build_flowchart_with_nodes
|
39
|
+
end
|
40
|
+
|
41
|
+
def full_diagram_method
|
42
|
+
:build_flowchart_diagram_from_dataset
|
43
|
+
end
|
49
44
|
end
|
50
45
|
end
|
51
46
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base_diagram_strategy"
|
4
|
+
require_relative "diagram_strategy_helpers"
|
5
|
+
|
6
|
+
module Dbwatcher
|
7
|
+
module Services
|
8
|
+
module DiagramStrategies
|
9
|
+
# Standard diagram strategy implementation
|
10
|
+
#
|
11
|
+
# Provides a common implementation for diagram strategies that follow
|
12
|
+
# the standard pattern of generating diagrams from datasets.
|
13
|
+
# Specific strategies can inherit from this class and provide only
|
14
|
+
# the necessary configuration.
|
15
|
+
class StandardDiagramStrategy < BaseDiagramStrategy
|
16
|
+
include DiagramStrategyHelpers
|
17
|
+
|
18
|
+
# Initialize with configuration options
|
19
|
+
#
|
20
|
+
# @param dependencies [Hash] injected dependencies
|
21
|
+
# @option dependencies [Object] :syntax_builder Mermaid syntax builder
|
22
|
+
# @option dependencies [Logger] :logger logger instance
|
23
|
+
def initialize(dependencies = {})
|
24
|
+
super
|
25
|
+
@diagram_options = diagram_options
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
# Generate diagram content from dataset using standard pattern
|
31
|
+
#
|
32
|
+
# @param dataset [Dataset] standardized dataset
|
33
|
+
# @return [String] diagram content
|
34
|
+
def generate_diagram_content(dataset)
|
35
|
+
generate_standard_diagram_content(dataset, @diagram_options)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Get diagram generation options
|
39
|
+
#
|
40
|
+
# @return [Hash] diagram options
|
41
|
+
def diagram_options
|
42
|
+
{
|
43
|
+
empty_method: empty_diagram_method,
|
44
|
+
empty_message: empty_diagram_message,
|
45
|
+
empty_entities_method: empty_entities_method,
|
46
|
+
full_diagram_method: full_diagram_method
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get method name for generating empty diagram
|
51
|
+
#
|
52
|
+
# @return [Symbol] method name
|
53
|
+
def empty_diagram_method
|
54
|
+
raise NotImplementedError, "Subclasses must implement empty_diagram_method"
|
55
|
+
end
|
56
|
+
|
57
|
+
# Get message for empty diagram
|
58
|
+
#
|
59
|
+
# @return [String] empty diagram message
|
60
|
+
def empty_diagram_message
|
61
|
+
"No data available for diagram"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get method name for generating diagram with only entities
|
65
|
+
#
|
66
|
+
# @return [Symbol] method name
|
67
|
+
def empty_entities_method
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
|
71
|
+
# Get method name for generating full diagram
|
72
|
+
#
|
73
|
+
# @return [Symbol] method name
|
74
|
+
def full_diagram_method
|
75
|
+
raise NotImplementedError, "Subclasses must implement full_diagram_method"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -29,6 +29,8 @@ require_relative "diagram_analyzers/model_association_analyzer"
|
|
29
29
|
|
30
30
|
# Diagram strategies
|
31
31
|
require_relative "diagram_strategies/base_diagram_strategy"
|
32
|
+
require_relative "diagram_strategies/diagram_strategy_helpers"
|
33
|
+
require_relative "diagram_strategies/standard_diagram_strategy"
|
32
34
|
require_relative "diagram_strategies/erd_diagram_strategy"
|
33
35
|
require_relative "diagram_strategies/class_diagram_strategy"
|
34
36
|
require_relative "diagram_strategies/flowchart_diagram_strategy"
|
@@ -41,6 +43,13 @@ module Dbwatcher
|
|
41
43
|
# Diagram System Module
|
42
44
|
# Provides centralized access to diagram generation capabilities
|
43
45
|
module DiagramSystem
|
46
|
+
extend Dbwatcher::Logging
|
47
|
+
|
48
|
+
# Explicitly set the component name for logging
|
49
|
+
def self.component_name
|
50
|
+
"DiagramSystem"
|
51
|
+
end
|
52
|
+
|
44
53
|
# Get available diagram types
|
45
54
|
#
|
46
55
|
# @return [Array<String>] available diagram type names
|
@@ -54,7 +63,11 @@ module Dbwatcher
|
|
54
63
|
# @param diagram_type [String] type of diagram to generate
|
55
64
|
# @return [Hash] diagram generation result
|
56
65
|
def self.generate(session_id, diagram_type = "database_tables")
|
57
|
-
|
66
|
+
log_debug("Generating diagram of type #{diagram_type} for session #{session_id}")
|
67
|
+
generator = DiagramGenerator.new(session_id: session_id, diagram_type: diagram_type)
|
68
|
+
result = generator.call
|
69
|
+
log_debug("Diagram generation completed with success=#{result[:success]}")
|
70
|
+
result
|
58
71
|
end
|
59
72
|
|
60
73
|
# Check if diagram type is supported
|
@@ -15,6 +15,8 @@ module Dbwatcher
|
|
15
15
|
# content = builder.build_erd_diagram_from_dataset(dataset)
|
16
16
|
# # => "erDiagram\n USERS ||--o{ ORDERS : user_id"
|
17
17
|
class MermaidSyntaxBuilder
|
18
|
+
include Dbwatcher::Logging
|
19
|
+
|
18
20
|
# Custom error classes
|
19
21
|
class SyntaxValidationError < StandardError; end
|
20
22
|
class UnsupportedDiagramTypeError < StandardError; end
|
@@ -40,8 +42,8 @@ module Dbwatcher
|
|
40
42
|
# @param options [Hash] generation options
|
41
43
|
# @return [String] Mermaid ERD syntax
|
42
44
|
def build_erd_diagram_from_dataset(dataset, options = {})
|
43
|
-
|
44
|
-
|
45
|
+
log_debug("Building ERD diagram from dataset with #{dataset.entities.size} entities and " \
|
46
|
+
"#{dataset.relationships.size} relationships")
|
45
47
|
|
46
48
|
builder = MermaidSyntax::ErdBuilder.new(@config.merge(options))
|
47
49
|
builder.build_from_dataset(dataset)
|
@@ -53,8 +55,8 @@ module Dbwatcher
|
|
53
55
|
# @param options [Hash] generation options
|
54
56
|
# @return [String] Mermaid class diagram syntax
|
55
57
|
def build_class_diagram_from_dataset(dataset, options = {})
|
56
|
-
|
57
|
-
|
58
|
+
log_debug("Building class diagram from dataset with #{dataset.entities.size} entities and " \
|
59
|
+
"#{dataset.relationships.size} relationships")
|
58
60
|
|
59
61
|
builder = MermaidSyntax::ClassDiagramBuilder.new(@config.merge(options))
|
60
62
|
builder.build_from_dataset(dataset)
|
@@ -66,8 +68,8 @@ module Dbwatcher
|
|
66
68
|
# @param options [Hash] generation options
|
67
69
|
# @return [String] Mermaid flowchart syntax
|
68
70
|
def build_flowchart_diagram_from_dataset(dataset, options = {})
|
69
|
-
|
70
|
-
|
71
|
+
log_debug("Building flowchart diagram from dataset with #{dataset.entities.size} entities and " \
|
72
|
+
"#{dataset.relationships.size} relationships")
|
71
73
|
|
72
74
|
builder = MermaidSyntax::FlowchartBuilder.new(@config.merge(options))
|
73
75
|
builder.build_from_dataset(dataset)
|
@@ -125,7 +127,7 @@ module Dbwatcher
|
|
125
127
|
# @param options [Hash] generation options
|
126
128
|
# @return [String] Mermaid ERD syntax
|
127
129
|
def build_erd_diagram_with_tables(entities, options = {})
|
128
|
-
|
130
|
+
log_debug("Building ERD diagram with #{entities.size} isolated tables")
|
129
131
|
|
130
132
|
dataset = Dbwatcher::Services::DiagramData::Dataset.new
|
131
133
|
entities.each { |entity| dataset.add_entity(entity) }
|
@@ -139,7 +141,7 @@ module Dbwatcher
|
|
139
141
|
# @param options [Hash] generation options
|
140
142
|
# @return [String] Mermaid flowchart syntax
|
141
143
|
def build_flowchart_with_nodes(entities, options = {})
|
142
|
-
|
144
|
+
log_debug("Building flowchart diagram with #{entities.size} isolated nodes")
|
143
145
|
|
144
146
|
dataset = Dbwatcher::Services::DiagramData::Dataset.new
|
145
147
|
entities.each { |entity| dataset.add_entity(entity) }
|