dbwatcher 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +81 -210
- data/app/assets/config/dbwatcher_manifest.js +15 -0
- data/app/assets/javascripts/dbwatcher/alpine_registrations.js +39 -0
- data/app/assets/javascripts/dbwatcher/auto_init.js +23 -0
- data/app/assets/javascripts/dbwatcher/components/base.js +141 -0
- data/app/assets/javascripts/dbwatcher/components/changes_table_hybrid.js +1008 -0
- data/app/assets/javascripts/dbwatcher/components/diagrams.js +449 -0
- data/app/assets/javascripts/dbwatcher/components/summary.js +234 -0
- data/app/assets/javascripts/dbwatcher/core/alpine_store.js +138 -0
- data/app/assets/javascripts/dbwatcher/core/api_client.js +162 -0
- data/app/assets/javascripts/dbwatcher/core/component_loader.js +70 -0
- data/app/assets/javascripts/dbwatcher/core/component_registry.js +94 -0
- data/app/assets/javascripts/dbwatcher/dbwatcher.js +120 -0
- data/app/assets/javascripts/dbwatcher/services/mermaid.js +315 -0
- data/app/assets/javascripts/dbwatcher/services/mermaid_service.js +199 -0
- data/app/assets/javascripts/dbwatcher/vendor/date-fns-browser.js +99 -0
- data/app/assets/javascripts/dbwatcher/vendor/lodash.min.js +140 -0
- data/app/assets/javascripts/dbwatcher/vendor/tabulator.min.js +3 -0
- data/app/assets/stylesheets/dbwatcher/application.css +423 -0
- data/app/assets/stylesheets/dbwatcher/application.scss +15 -0
- data/app/assets/stylesheets/dbwatcher/components/_badges.scss +38 -0
- data/app/assets/stylesheets/dbwatcher/components/_compact_table.scss +162 -0
- data/app/assets/stylesheets/dbwatcher/components/_diagrams.scss +51 -0
- data/app/assets/stylesheets/dbwatcher/components/_forms.scss +27 -0
- data/app/assets/stylesheets/dbwatcher/components/_navigation.scss +55 -0
- data/app/assets/stylesheets/dbwatcher/core/_base.scss +34 -0
- data/app/assets/stylesheets/dbwatcher/core/_variables.scss +47 -0
- data/app/assets/stylesheets/dbwatcher/vendor/tabulator.min.css +2 -0
- data/app/controllers/dbwatcher/api/v1/sessions_controller.rb +64 -0
- data/app/controllers/dbwatcher/base_controller.rb +8 -2
- data/app/controllers/dbwatcher/dashboard_controller.rb +8 -0
- data/app/controllers/dbwatcher/sessions_controller.rb +25 -10
- data/app/helpers/dbwatcher/component_helper.rb +29 -0
- data/app/helpers/dbwatcher/diagram_helper.rb +110 -0
- data/app/helpers/dbwatcher/session_helper.rb +3 -2
- data/app/views/dbwatcher/sessions/_changes_tab.html.erb +265 -0
- data/app/views/dbwatcher/sessions/_diagrams_tab.html.erb +166 -0
- data/app/views/dbwatcher/sessions/_session_header.html.erb +11 -0
- data/app/views/dbwatcher/sessions/_summary_tab.html.erb +88 -0
- data/app/views/dbwatcher/sessions/_tab_navigation.html.erb +12 -0
- data/app/views/dbwatcher/sessions/changes.html.erb +21 -0
- data/app/views/dbwatcher/sessions/components/changes/_filters.html.erb +44 -0
- data/app/views/dbwatcher/sessions/components/changes/_table_list.html.erb +96 -0
- data/app/views/dbwatcher/sessions/diagrams.html.erb +21 -0
- data/app/views/dbwatcher/sessions/index.html.erb +14 -10
- data/app/views/dbwatcher/sessions/shared/_layout.html.erb +8 -0
- data/app/views/dbwatcher/sessions/shared/_navigation.html.erb +35 -0
- data/app/views/dbwatcher/sessions/shared/_session_header.html.erb +25 -0
- data/app/views/dbwatcher/sessions/show.html.erb +3 -346
- data/app/views/dbwatcher/sessions/summary.html.erb +21 -0
- data/app/views/layouts/dbwatcher/application.html.erb +125 -247
- data/bin/compile_scss +49 -0
- data/config/routes.rb +26 -0
- data/lib/dbwatcher/configuration.rb +102 -8
- data/lib/dbwatcher/engine.rb +17 -7
- data/lib/dbwatcher/services/analyzers/session_data_processor.rb +98 -0
- data/lib/dbwatcher/services/analyzers/table_summary_builder.rb +202 -0
- data/lib/dbwatcher/services/api/base_api_service.rb +100 -0
- data/lib/dbwatcher/services/api/changes_data_service.rb +112 -0
- data/lib/dbwatcher/services/api/diagram_data_service.rb +145 -0
- data/lib/dbwatcher/services/api/summary_data_service.rb +158 -0
- data/lib/dbwatcher/services/base_service.rb +64 -0
- data/lib/dbwatcher/services/diagram_analyzers/base_analyzer.rb +162 -0
- data/lib/dbwatcher/services/diagram_analyzers/foreign_key_analyzer.rb +354 -0
- data/lib/dbwatcher/services/diagram_analyzers/inferred_relationship_analyzer.rb +502 -0
- data/lib/dbwatcher/services/diagram_analyzers/model_association_analyzer.rb +564 -0
- data/lib/dbwatcher/services/diagram_data/attribute.rb +154 -0
- data/lib/dbwatcher/services/diagram_data/dataset.rb +278 -0
- data/lib/dbwatcher/services/diagram_data/entity.rb +180 -0
- data/lib/dbwatcher/services/diagram_data/relationship.rb +188 -0
- data/lib/dbwatcher/services/diagram_data/relationship_params.rb +55 -0
- data/lib/dbwatcher/services/diagram_data.rb +65 -0
- data/lib/dbwatcher/services/diagram_error_handler.rb +239 -0
- data/lib/dbwatcher/services/diagram_generator.rb +154 -0
- data/lib/dbwatcher/services/diagram_strategies/base_diagram_strategy.rb +149 -0
- data/lib/dbwatcher/services/diagram_strategies/class_diagram_strategy.rb +49 -0
- data/lib/dbwatcher/services/diagram_strategies/erd_diagram_strategy.rb +52 -0
- data/lib/dbwatcher/services/diagram_strategies/flowchart_diagram_strategy.rb +52 -0
- data/lib/dbwatcher/services/diagram_system.rb +69 -0
- data/lib/dbwatcher/services/diagram_type_registry.rb +164 -0
- data/lib/dbwatcher/services/mermaid_syntax/base_builder.rb +127 -0
- data/lib/dbwatcher/services/mermaid_syntax/cardinality_mapper.rb +90 -0
- data/lib/dbwatcher/services/mermaid_syntax/class_diagram_builder.rb +136 -0
- data/lib/dbwatcher/services/mermaid_syntax/class_diagram_helper.rb +46 -0
- data/lib/dbwatcher/services/mermaid_syntax/erd_builder.rb +116 -0
- data/lib/dbwatcher/services/mermaid_syntax/flowchart_builder.rb +109 -0
- data/lib/dbwatcher/services/mermaid_syntax/sanitizer.rb +102 -0
- data/lib/dbwatcher/services/mermaid_syntax_builder.rb +155 -0
- data/lib/dbwatcher/storage/api/concerns/table_analyzer.rb +15 -128
- data/lib/dbwatcher/storage/api/session_api.rb +47 -0
- data/lib/dbwatcher/storage/base_storage.rb +7 -0
- data/lib/dbwatcher/version.rb +1 -1
- data/lib/dbwatcher.rb +58 -1
- metadata +94 -2
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
require "digest"
|
5
|
+
|
6
|
+
module Dbwatcher
|
7
|
+
module Services
|
8
|
+
# Builder for generating validated Mermaid diagram syntax
|
9
|
+
#
|
10
|
+
# Provides methods for building different types of Mermaid diagrams with
|
11
|
+
# syntax validation, error checking, and consistent formatting.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# builder = MermaidSyntaxBuilder.new
|
15
|
+
# content = builder.build_erd_diagram_from_dataset(dataset)
|
16
|
+
# # => "erDiagram\n USERS ||--o{ ORDERS : user_id"
|
17
|
+
class MermaidSyntaxBuilder
|
18
|
+
# Custom error classes
|
19
|
+
class SyntaxValidationError < StandardError; end
|
20
|
+
class UnsupportedDiagramTypeError < StandardError; end
|
21
|
+
|
22
|
+
# Supported Mermaid diagram types
|
23
|
+
SUPPORTED_DIAGRAM_TYPES = %w[erDiagram classDiagram flowchart graph].freeze
|
24
|
+
|
25
|
+
# Maximum content length to prevent memory issues
|
26
|
+
MAX_CONTENT_LENGTH = 100_000
|
27
|
+
|
28
|
+
# Initialize builder
|
29
|
+
#
|
30
|
+
# @param config [Hash] builder configuration (optional)
|
31
|
+
# @option config [Logger] :logger logger instance
|
32
|
+
def initialize(config = {})
|
33
|
+
@config = config
|
34
|
+
@logger = config[:logger] || Rails.logger
|
35
|
+
end
|
36
|
+
|
37
|
+
# Build ERD diagram from dataset
|
38
|
+
#
|
39
|
+
# @param dataset [DiagramData::Dataset] dataset to render
|
40
|
+
# @param options [Hash] generation options
|
41
|
+
# @return [String] Mermaid ERD syntax
|
42
|
+
def build_erd_diagram_from_dataset(dataset, options = {})
|
43
|
+
@logger.debug "Building ERD diagram from dataset with #{dataset.entities.size} entities and " \
|
44
|
+
"#{dataset.relationships.size} relationships"
|
45
|
+
|
46
|
+
builder = MermaidSyntax::ErdBuilder.new(@config.merge(options))
|
47
|
+
builder.build_from_dataset(dataset)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Build class diagram from dataset
|
51
|
+
#
|
52
|
+
# @param dataset [DiagramData::Dataset] dataset to render
|
53
|
+
# @param options [Hash] generation options
|
54
|
+
# @return [String] Mermaid class diagram syntax
|
55
|
+
def build_class_diagram_from_dataset(dataset, options = {})
|
56
|
+
@logger.debug "Building class diagram from dataset with #{dataset.entities.size} entities and " \
|
57
|
+
"#{dataset.relationships.size} relationships"
|
58
|
+
|
59
|
+
builder = MermaidSyntax::ClassDiagramBuilder.new(@config.merge(options))
|
60
|
+
builder.build_from_dataset(dataset)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Build flowchart diagram from dataset
|
64
|
+
#
|
65
|
+
# @param dataset [DiagramData::Dataset] dataset to render
|
66
|
+
# @param options [Hash] generation options
|
67
|
+
# @return [String] Mermaid flowchart syntax
|
68
|
+
def build_flowchart_diagram_from_dataset(dataset, options = {})
|
69
|
+
@logger.debug "Building flowchart diagram from dataset with #{dataset.entities.size} entities and " \
|
70
|
+
"#{dataset.relationships.size} relationships"
|
71
|
+
|
72
|
+
builder = MermaidSyntax::FlowchartBuilder.new(@config.merge(options))
|
73
|
+
builder.build_from_dataset(dataset)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Build empty ERD diagram with message
|
77
|
+
#
|
78
|
+
# @param message [String] message to display
|
79
|
+
# @return [String] Mermaid ERD syntax
|
80
|
+
def build_empty_erd(message)
|
81
|
+
builder = MermaidSyntax::ErdBuilder.new(@config)
|
82
|
+
builder.build_empty(message)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Build empty flowchart diagram with message
|
86
|
+
#
|
87
|
+
# @param message [String] message to display
|
88
|
+
# @return [String] Mermaid flowchart syntax
|
89
|
+
def build_empty_flowchart(message)
|
90
|
+
builder = MermaidSyntax::FlowchartBuilder.new(@config)
|
91
|
+
builder.build_empty(message)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Build empty class diagram with message
|
95
|
+
#
|
96
|
+
# @param message [String] message to display
|
97
|
+
# @return [String] Mermaid class diagram syntax
|
98
|
+
def build_empty_class_diagram(message)
|
99
|
+
builder = MermaidSyntax::ClassDiagramBuilder.new(@config)
|
100
|
+
builder.build_empty(message)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Build empty diagram of specified type
|
104
|
+
#
|
105
|
+
# @param message [String] message to display
|
106
|
+
# @param diagram_type [String] type of diagram
|
107
|
+
# @return [String] Mermaid syntax
|
108
|
+
# @raise [UnsupportedDiagramTypeError] if type unsupported
|
109
|
+
def build_empty_diagram(message, diagram_type)
|
110
|
+
case diagram_type
|
111
|
+
when "erDiagram", "erd"
|
112
|
+
build_empty_erd(message)
|
113
|
+
when "classDiagram", "class"
|
114
|
+
build_empty_class_diagram(message)
|
115
|
+
when "flowchart", "graph"
|
116
|
+
build_empty_flowchart(message)
|
117
|
+
else
|
118
|
+
raise UnsupportedDiagramTypeError, "Unsupported diagram type: #{diagram_type}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Build ERD diagram with isolated tables
|
123
|
+
#
|
124
|
+
# @param entities [Array<Entity>] isolated table entities
|
125
|
+
# @param options [Hash] generation options
|
126
|
+
# @return [String] Mermaid ERD syntax
|
127
|
+
def build_erd_diagram_with_tables(entities, options = {})
|
128
|
+
@logger.debug "Building ERD diagram with #{entities.size} isolated tables"
|
129
|
+
|
130
|
+
dataset = Dbwatcher::Services::DiagramData::Dataset.new
|
131
|
+
entities.each { |entity| dataset.add_entity(entity) }
|
132
|
+
|
133
|
+
build_erd_diagram_from_dataset(dataset, options)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Build flowchart diagram with isolated nodes
|
137
|
+
#
|
138
|
+
# @param entities [Array<Entity>] isolated node entities
|
139
|
+
# @param options [Hash] generation options
|
140
|
+
# @return [String] Mermaid flowchart syntax
|
141
|
+
def build_flowchart_with_nodes(entities, options = {})
|
142
|
+
@logger.debug "Building flowchart diagram with #{entities.size} isolated nodes"
|
143
|
+
|
144
|
+
dataset = Dbwatcher::Services::DiagramData::Dataset.new
|
145
|
+
entities.each { |entity| dataset.add_entity(entity) }
|
146
|
+
|
147
|
+
build_flowchart_diagram_from_dataset(dataset, options)
|
148
|
+
end
|
149
|
+
|
150
|
+
# For backward compatibility with legacy code
|
151
|
+
alias build_erd_diagram build_erd_diagram_from_dataset
|
152
|
+
alias build_flowchart_diagram build_flowchart_diagram_from_dataset
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -6,8 +6,8 @@ module Dbwatcher
|
|
6
6
|
module Concerns
|
7
7
|
# Provides reusable table analysis functionality for API classes
|
8
8
|
#
|
9
|
-
# This concern
|
10
|
-
# to
|
9
|
+
# This concern now acts as a facade, delegating specific responsibilities
|
10
|
+
# to specialized service classes while maintaining backward compatibility.
|
11
11
|
#
|
12
12
|
# @example
|
13
13
|
# class MyAPI < BaseAPI
|
@@ -23,148 +23,35 @@ module Dbwatcher
|
|
23
23
|
# @param session [Session] session to analyze
|
24
24
|
# @return [Hash] tables summary hash
|
25
25
|
def build_tables_summary(session)
|
26
|
-
|
27
|
-
|
28
|
-
tables
|
26
|
+
# Delegate to new service while maintaining interface compatibility
|
27
|
+
Dbwatcher::Services::Analyzers::TableSummaryBuilder.call(session)
|
29
28
|
end
|
30
29
|
|
31
|
-
# Process all changes in a session
|
30
|
+
# Process all changes in a session (legacy method for backward compatibility)
|
32
31
|
#
|
33
32
|
# @param session [Session] session with changes
|
34
|
-
# @param
|
33
|
+
# @param _tables [Hash] tables hash to populate (unused but kept for compatibility)
|
35
34
|
# @return [void]
|
36
|
-
def process_session_changes(session,
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
table_name
|
41
|
-
next unless table_name
|
42
|
-
|
43
|
-
initialize_table_data(tables, table_name)
|
44
|
-
update_table_data(tables[table_name], change)
|
45
|
-
update_sample_record(tables[table_name], change)
|
35
|
+
def process_session_changes(session, _tables)
|
36
|
+
# Use new service for processing but maintain yield interface
|
37
|
+
processor = Dbwatcher::Services::Analyzers::SessionDataProcessor.new(session)
|
38
|
+
processor.process_changes do |table_name, change, _|
|
39
|
+
yield(table_name, change) if block_given?
|
46
40
|
end
|
47
41
|
end
|
48
42
|
|
49
|
-
#
|
43
|
+
# Legacy methods maintained for backward compatibility
|
44
|
+
# These now delegate to the new service classes
|
45
|
+
|
46
|
+
# Extract table name from change data (legacy compatibility)
|
50
47
|
#
|
51
48
|
# @param change [Hash] change data
|
52
49
|
# @return [String, nil] table name or nil
|
53
50
|
def extract_table_name(change)
|
54
51
|
return nil unless change.is_a?(Hash)
|
55
52
|
|
56
|
-
# Only use symbols since data is normalized
|
57
53
|
change[:table_name]
|
58
54
|
end
|
59
|
-
|
60
|
-
# Initialize table data structure
|
61
|
-
#
|
62
|
-
# @param tables [Hash] tables hash
|
63
|
-
# @param table_name [String] table name
|
64
|
-
# @return [void]
|
65
|
-
def initialize_table_data(tables, table_name)
|
66
|
-
tables[table_name] ||= {
|
67
|
-
name: table_name,
|
68
|
-
operations: { "INSERT" => 0, "UPDATE" => 0, "DELETE" => 0 },
|
69
|
-
changes: [],
|
70
|
-
sample_record: nil,
|
71
|
-
records: {},
|
72
|
-
relationships: []
|
73
|
-
}
|
74
|
-
end
|
75
|
-
|
76
|
-
# Update table data with change information
|
77
|
-
#
|
78
|
-
# @param table_data [Hash] table data hash
|
79
|
-
# @param change [Hash] change data
|
80
|
-
# @return [void]
|
81
|
-
def update_table_data(table_data, change)
|
82
|
-
# Count operations
|
83
|
-
operation = extract_operation(change)
|
84
|
-
table_data[:operations][operation] ||= 0
|
85
|
-
table_data[:operations][operation] += 1
|
86
|
-
|
87
|
-
# Add change to the list
|
88
|
-
table_data[:changes] << change
|
89
|
-
end
|
90
|
-
|
91
|
-
# Update sample record if not already set
|
92
|
-
#
|
93
|
-
# @param table_data [Hash] table data hash
|
94
|
-
# @param change [Hash] change data
|
95
|
-
# @return [void]
|
96
|
-
def update_sample_record(table_data, change)
|
97
|
-
return unless table_data[:sample_record].nil?
|
98
|
-
|
99
|
-
snapshot = extract_record_snapshot(change)
|
100
|
-
table_data[:sample_record] = snapshot if snapshot
|
101
|
-
end
|
102
|
-
|
103
|
-
# Update record history for analysis
|
104
|
-
#
|
105
|
-
# @param table_data [Hash] table data hash
|
106
|
-
# @param change [Hash] change data
|
107
|
-
# @return [void]
|
108
|
-
def update_record_history(table_data, change)
|
109
|
-
record_id = extract_record_id(change)
|
110
|
-
return unless record_id
|
111
|
-
|
112
|
-
table_data[:records][record_id] ||= []
|
113
|
-
table_data[:records][record_id] << {
|
114
|
-
operation: extract_operation(change),
|
115
|
-
timestamp: extract_timestamp(change),
|
116
|
-
changes: extract_field_changes(change)
|
117
|
-
}
|
118
|
-
end
|
119
|
-
|
120
|
-
private
|
121
|
-
|
122
|
-
# Extract operation from change data
|
123
|
-
#
|
124
|
-
# @param change [Hash] change data
|
125
|
-
# @return [String] operation string
|
126
|
-
def extract_operation(change)
|
127
|
-
# Only use symbols since data is normalized
|
128
|
-
operation = change[:operation] || "UNKNOWN"
|
129
|
-
operation.to_s.upcase
|
130
|
-
end
|
131
|
-
|
132
|
-
# Extract record snapshot from change data
|
133
|
-
#
|
134
|
-
# @param change [Hash] change data
|
135
|
-
# @return [Hash, nil] record snapshot or nil
|
136
|
-
def extract_record_snapshot(change)
|
137
|
-
# Only use symbols since data is normalized
|
138
|
-
change[:record_snapshot]
|
139
|
-
end
|
140
|
-
|
141
|
-
# Extract record ID from change data
|
142
|
-
#
|
143
|
-
# @param change [Hash] change data
|
144
|
-
# @return [String, nil] record ID or nil
|
145
|
-
def extract_record_id(change)
|
146
|
-
# Only use symbols since data is normalized
|
147
|
-
id = change[:record_id]
|
148
|
-
id&.to_s
|
149
|
-
end
|
150
|
-
|
151
|
-
# Extract timestamp from change data
|
152
|
-
#
|
153
|
-
# @param change [Hash] change data
|
154
|
-
# @return [String, nil] timestamp string or nil
|
155
|
-
def extract_timestamp(change)
|
156
|
-
# Only use symbols since data is normalized
|
157
|
-
change[:timestamp]
|
158
|
-
end
|
159
|
-
|
160
|
-
# Extract field changes from change data
|
161
|
-
#
|
162
|
-
# @param change [Hash] change data
|
163
|
-
# @return [Hash] field changes hash
|
164
|
-
def extract_field_changes(change)
|
165
|
-
# Only use symbols since data is normalized
|
166
|
-
change[:changes] || {}
|
167
|
-
end
|
168
55
|
end
|
169
56
|
end
|
170
57
|
end
|
@@ -91,6 +91,42 @@ module Dbwatcher
|
|
91
91
|
.first(limit)
|
92
92
|
end
|
93
93
|
|
94
|
+
# Get comprehensive session analysis including tables and relationships
|
95
|
+
#
|
96
|
+
# @param session_id [String] session identifier
|
97
|
+
# @return [Hash] session analysis data
|
98
|
+
def summary(session_id)
|
99
|
+
session = find(session_id)
|
100
|
+
return { error: "Session not found" } unless session
|
101
|
+
|
102
|
+
{
|
103
|
+
tables_summary: tables_summary(session_id),
|
104
|
+
total_changes: session.changes&.count || 0,
|
105
|
+
session_metadata: extract_session_metadata(session)
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
# Get tables summary for a session
|
110
|
+
#
|
111
|
+
# @param session_id [String] session identifier
|
112
|
+
# @return [Hash] tables summary
|
113
|
+
def tables_summary(session_id)
|
114
|
+
session = find(session_id)
|
115
|
+
return { error: "Session not found" } unless session
|
116
|
+
|
117
|
+
analyzer = Dbwatcher::Services::Analyzers::TableSummaryBuilder.new(session)
|
118
|
+
analyzer.call
|
119
|
+
end
|
120
|
+
|
121
|
+
# Generate diagram data for a session
|
122
|
+
#
|
123
|
+
# @param session_id [String] session identifier
|
124
|
+
# @param diagram_type [String] type of diagram to generate
|
125
|
+
# @return [Hash] diagram data
|
126
|
+
def diagram_data(session_id, diagram_type = "database_tables")
|
127
|
+
Dbwatcher::Services::DiagramSystem.generate(session_id, diagram_type)
|
128
|
+
end
|
129
|
+
|
94
130
|
private
|
95
131
|
|
96
132
|
def apply_filters(sessions)
|
@@ -128,6 +164,17 @@ module Dbwatcher
|
|
128
164
|
session&.changes&.any?
|
129
165
|
end
|
130
166
|
end
|
167
|
+
|
168
|
+
# Extract session metadata for analysis
|
169
|
+
#
|
170
|
+
# @param session [Session] session object
|
171
|
+
# @return [Hash] metadata hash
|
172
|
+
def extract_session_metadata(session)
|
173
|
+
{
|
174
|
+
id: session.id,
|
175
|
+
changes_count: session.changes&.count || 0
|
176
|
+
}
|
177
|
+
end
|
131
178
|
end
|
132
179
|
end
|
133
180
|
end
|
@@ -47,8 +47,15 @@ module Dbwatcher
|
|
47
47
|
# instance, and initializes timestamps.
|
48
48
|
#
|
49
49
|
# @param storage_path [String, nil] custom storage path (optional)
|
50
|
+
# @raise [StorageError] if storage_path is nil or empty
|
50
51
|
def initialize(storage_path = nil)
|
51
52
|
@storage_path = storage_path || Dbwatcher.configuration.storage_path
|
53
|
+
|
54
|
+
# Ensure storage path is valid
|
55
|
+
if @storage_path.nil? || @storage_path.to_s.strip.empty?
|
56
|
+
raise StorageError, "Storage path cannot be nil or empty. Please configure a valid storage path."
|
57
|
+
end
|
58
|
+
|
52
59
|
@file_manager = FileManager.new(@storage_path)
|
53
60
|
initialize_timestamps
|
54
61
|
ensure_storage_directory
|
data/lib/dbwatcher/version.rb
CHANGED
data/lib/dbwatcher.rb
CHANGED
@@ -5,17 +5,74 @@ require "fileutils"
|
|
5
5
|
require "securerandom"
|
6
6
|
require "singleton"
|
7
7
|
require "logger"
|
8
|
+
|
9
|
+
# Core components
|
8
10
|
require_relative "dbwatcher/version"
|
9
11
|
require_relative "dbwatcher/configuration"
|
10
12
|
require_relative "dbwatcher/logging"
|
11
|
-
|
13
|
+
|
14
|
+
# Storage layer
|
12
15
|
require_relative "dbwatcher/storage"
|
16
|
+
|
17
|
+
# Tracking and SQL monitoring
|
18
|
+
require_relative "dbwatcher/tracker"
|
13
19
|
require_relative "dbwatcher/sql_logger"
|
14
20
|
require_relative "dbwatcher/model_extension"
|
15
21
|
require_relative "dbwatcher/middleware"
|
22
|
+
|
23
|
+
# Base services
|
24
|
+
require_relative "dbwatcher/services/base_service"
|
25
|
+
|
26
|
+
# Core services
|
16
27
|
require_relative "dbwatcher/services/table_statistics_collector"
|
17
28
|
require_relative "dbwatcher/services/dashboard_data_aggregator"
|
18
29
|
require_relative "dbwatcher/services/query_filter_processor"
|
30
|
+
|
31
|
+
# General analyzers
|
32
|
+
require_relative "dbwatcher/services/analyzers/session_data_processor"
|
33
|
+
require_relative "dbwatcher/services/analyzers/table_summary_builder"
|
34
|
+
|
35
|
+
# Diagram data models
|
36
|
+
require_relative "dbwatcher/services/diagram_data/attribute"
|
37
|
+
require_relative "dbwatcher/services/diagram_data/entity"
|
38
|
+
require_relative "dbwatcher/services/diagram_data/relationship"
|
39
|
+
require_relative "dbwatcher/services/diagram_data/dataset"
|
40
|
+
require_relative "dbwatcher/services/diagram_data"
|
41
|
+
|
42
|
+
# Diagram analyzers
|
43
|
+
require_relative "dbwatcher/services/diagram_analyzers/base_analyzer"
|
44
|
+
require_relative "dbwatcher/services/diagram_analyzers/foreign_key_analyzer"
|
45
|
+
require_relative "dbwatcher/services/diagram_analyzers/inferred_relationship_analyzer"
|
46
|
+
require_relative "dbwatcher/services/diagram_analyzers/model_association_analyzer"
|
47
|
+
|
48
|
+
# Mermaid syntax builders
|
49
|
+
require_relative "dbwatcher/services/mermaid_syntax/base_builder"
|
50
|
+
require_relative "dbwatcher/services/mermaid_syntax/sanitizer"
|
51
|
+
require_relative "dbwatcher/services/mermaid_syntax/cardinality_mapper"
|
52
|
+
require_relative "dbwatcher/services/mermaid_syntax/erd_builder"
|
53
|
+
require_relative "dbwatcher/services/mermaid_syntax/class_diagram_builder"
|
54
|
+
require_relative "dbwatcher/services/mermaid_syntax/flowchart_builder"
|
55
|
+
require_relative "dbwatcher/services/mermaid_syntax_builder"
|
56
|
+
|
57
|
+
# Diagram strategies
|
58
|
+
require_relative "dbwatcher/services/diagram_strategies/base_diagram_strategy"
|
59
|
+
require_relative "dbwatcher/services/diagram_strategies/erd_diagram_strategy"
|
60
|
+
require_relative "dbwatcher/services/diagram_strategies/class_diagram_strategy"
|
61
|
+
require_relative "dbwatcher/services/diagram_strategies/flowchart_diagram_strategy"
|
62
|
+
|
63
|
+
# Diagram system
|
64
|
+
require_relative "dbwatcher/services/diagram_error_handler"
|
65
|
+
require_relative "dbwatcher/services/diagram_type_registry"
|
66
|
+
require_relative "dbwatcher/services/diagram_generator"
|
67
|
+
require_relative "dbwatcher/services/diagram_system"
|
68
|
+
|
69
|
+
# API services
|
70
|
+
require_relative "dbwatcher/services/api/base_api_service"
|
71
|
+
require_relative "dbwatcher/services/api/changes_data_service"
|
72
|
+
require_relative "dbwatcher/services/api/summary_data_service"
|
73
|
+
require_relative "dbwatcher/services/api/diagram_data_service"
|
74
|
+
|
75
|
+
# Rails engine
|
19
76
|
require_relative "dbwatcher/engine" if defined?(Rails)
|
20
77
|
|
21
78
|
module Dbwatcher
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbwatcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Huy Nguyen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '6.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sassc
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.4'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.4'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: selenium-webdriver
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -141,6 +155,7 @@ description: DB Watcher helps developers debug Rails applications by tracking al
|
|
141
155
|
email:
|
142
156
|
- patrick204nqh@gmail.com
|
143
157
|
executables:
|
158
|
+
- compile_scss
|
144
159
|
- console
|
145
160
|
- release
|
146
161
|
- setup
|
@@ -149,18 +164,61 @@ extra_rdoc_files: []
|
|
149
164
|
files:
|
150
165
|
- README.md
|
151
166
|
- Rakefile
|
167
|
+
- app/assets/config/dbwatcher_manifest.js
|
168
|
+
- app/assets/javascripts/dbwatcher/alpine_registrations.js
|
169
|
+
- app/assets/javascripts/dbwatcher/auto_init.js
|
170
|
+
- app/assets/javascripts/dbwatcher/components/base.js
|
171
|
+
- app/assets/javascripts/dbwatcher/components/changes_table_hybrid.js
|
172
|
+
- app/assets/javascripts/dbwatcher/components/diagrams.js
|
173
|
+
- app/assets/javascripts/dbwatcher/components/summary.js
|
174
|
+
- app/assets/javascripts/dbwatcher/core/alpine_store.js
|
175
|
+
- app/assets/javascripts/dbwatcher/core/api_client.js
|
176
|
+
- app/assets/javascripts/dbwatcher/core/component_loader.js
|
177
|
+
- app/assets/javascripts/dbwatcher/core/component_registry.js
|
178
|
+
- app/assets/javascripts/dbwatcher/dbwatcher.js
|
179
|
+
- app/assets/javascripts/dbwatcher/services/mermaid.js
|
180
|
+
- app/assets/javascripts/dbwatcher/services/mermaid_service.js
|
181
|
+
- app/assets/javascripts/dbwatcher/vendor/date-fns-browser.js
|
182
|
+
- app/assets/javascripts/dbwatcher/vendor/lodash.min.js
|
183
|
+
- app/assets/javascripts/dbwatcher/vendor/tabulator.min.js
|
184
|
+
- app/assets/stylesheets/dbwatcher/application.css
|
185
|
+
- app/assets/stylesheets/dbwatcher/application.scss
|
186
|
+
- app/assets/stylesheets/dbwatcher/components/_badges.scss
|
187
|
+
- app/assets/stylesheets/dbwatcher/components/_compact_table.scss
|
188
|
+
- app/assets/stylesheets/dbwatcher/components/_diagrams.scss
|
189
|
+
- app/assets/stylesheets/dbwatcher/components/_forms.scss
|
190
|
+
- app/assets/stylesheets/dbwatcher/components/_navigation.scss
|
191
|
+
- app/assets/stylesheets/dbwatcher/core/_base.scss
|
192
|
+
- app/assets/stylesheets/dbwatcher/core/_variables.scss
|
193
|
+
- app/assets/stylesheets/dbwatcher/vendor/tabulator.min.css
|
194
|
+
- app/controllers/dbwatcher/api/v1/sessions_controller.rb
|
152
195
|
- app/controllers/dbwatcher/base_controller.rb
|
153
196
|
- app/controllers/dbwatcher/dashboard_controller.rb
|
154
197
|
- app/controllers/dbwatcher/queries_controller.rb
|
155
198
|
- app/controllers/dbwatcher/sessions_controller.rb
|
156
199
|
- app/controllers/dbwatcher/tables_controller.rb
|
157
200
|
- app/helpers/dbwatcher/application_helper.rb
|
201
|
+
- app/helpers/dbwatcher/component_helper.rb
|
202
|
+
- app/helpers/dbwatcher/diagram_helper.rb
|
158
203
|
- app/helpers/dbwatcher/formatting_helper.rb
|
159
204
|
- app/helpers/dbwatcher/session_helper.rb
|
160
205
|
- app/views/dbwatcher/dashboard/index.html.erb
|
161
206
|
- app/views/dbwatcher/queries/index.html.erb
|
207
|
+
- app/views/dbwatcher/sessions/_changes_tab.html.erb
|
208
|
+
- app/views/dbwatcher/sessions/_diagrams_tab.html.erb
|
209
|
+
- app/views/dbwatcher/sessions/_session_header.html.erb
|
210
|
+
- app/views/dbwatcher/sessions/_summary_tab.html.erb
|
211
|
+
- app/views/dbwatcher/sessions/_tab_navigation.html.erb
|
212
|
+
- app/views/dbwatcher/sessions/changes.html.erb
|
213
|
+
- app/views/dbwatcher/sessions/components/changes/_filters.html.erb
|
214
|
+
- app/views/dbwatcher/sessions/components/changes/_table_list.html.erb
|
215
|
+
- app/views/dbwatcher/sessions/diagrams.html.erb
|
162
216
|
- app/views/dbwatcher/sessions/index.html.erb
|
217
|
+
- app/views/dbwatcher/sessions/shared/_layout.html.erb
|
218
|
+
- app/views/dbwatcher/sessions/shared/_navigation.html.erb
|
219
|
+
- app/views/dbwatcher/sessions/shared/_session_header.html.erb
|
163
220
|
- app/views/dbwatcher/sessions/show.html.erb
|
221
|
+
- app/views/dbwatcher/sessions/summary.html.erb
|
164
222
|
- app/views/dbwatcher/shared/_badge.html.erb
|
165
223
|
- app/views/dbwatcher/shared/_data_table.html.erb
|
166
224
|
- app/views/dbwatcher/shared/_header.html.erb
|
@@ -172,6 +230,7 @@ files:
|
|
172
230
|
- app/views/dbwatcher/tables/index.html.erb
|
173
231
|
- app/views/dbwatcher/tables/show.html.erb
|
174
232
|
- app/views/layouts/dbwatcher/application.html.erb
|
233
|
+
- bin/compile_scss
|
175
234
|
- bin/console
|
176
235
|
- bin/release
|
177
236
|
- bin/setup
|
@@ -182,7 +241,40 @@ files:
|
|
182
241
|
- lib/dbwatcher/logging.rb
|
183
242
|
- lib/dbwatcher/middleware.rb
|
184
243
|
- lib/dbwatcher/model_extension.rb
|
244
|
+
- lib/dbwatcher/services/analyzers/session_data_processor.rb
|
245
|
+
- lib/dbwatcher/services/analyzers/table_summary_builder.rb
|
246
|
+
- lib/dbwatcher/services/api/base_api_service.rb
|
247
|
+
- lib/dbwatcher/services/api/changes_data_service.rb
|
248
|
+
- lib/dbwatcher/services/api/diagram_data_service.rb
|
249
|
+
- lib/dbwatcher/services/api/summary_data_service.rb
|
250
|
+
- lib/dbwatcher/services/base_service.rb
|
185
251
|
- lib/dbwatcher/services/dashboard_data_aggregator.rb
|
252
|
+
- lib/dbwatcher/services/diagram_analyzers/base_analyzer.rb
|
253
|
+
- lib/dbwatcher/services/diagram_analyzers/foreign_key_analyzer.rb
|
254
|
+
- lib/dbwatcher/services/diagram_analyzers/inferred_relationship_analyzer.rb
|
255
|
+
- lib/dbwatcher/services/diagram_analyzers/model_association_analyzer.rb
|
256
|
+
- lib/dbwatcher/services/diagram_data.rb
|
257
|
+
- lib/dbwatcher/services/diagram_data/attribute.rb
|
258
|
+
- lib/dbwatcher/services/diagram_data/dataset.rb
|
259
|
+
- lib/dbwatcher/services/diagram_data/entity.rb
|
260
|
+
- lib/dbwatcher/services/diagram_data/relationship.rb
|
261
|
+
- lib/dbwatcher/services/diagram_data/relationship_params.rb
|
262
|
+
- lib/dbwatcher/services/diagram_error_handler.rb
|
263
|
+
- lib/dbwatcher/services/diagram_generator.rb
|
264
|
+
- lib/dbwatcher/services/diagram_strategies/base_diagram_strategy.rb
|
265
|
+
- lib/dbwatcher/services/diagram_strategies/class_diagram_strategy.rb
|
266
|
+
- lib/dbwatcher/services/diagram_strategies/erd_diagram_strategy.rb
|
267
|
+
- lib/dbwatcher/services/diagram_strategies/flowchart_diagram_strategy.rb
|
268
|
+
- lib/dbwatcher/services/diagram_system.rb
|
269
|
+
- lib/dbwatcher/services/diagram_type_registry.rb
|
270
|
+
- lib/dbwatcher/services/mermaid_syntax/base_builder.rb
|
271
|
+
- lib/dbwatcher/services/mermaid_syntax/cardinality_mapper.rb
|
272
|
+
- lib/dbwatcher/services/mermaid_syntax/class_diagram_builder.rb
|
273
|
+
- lib/dbwatcher/services/mermaid_syntax/class_diagram_helper.rb
|
274
|
+
- lib/dbwatcher/services/mermaid_syntax/erd_builder.rb
|
275
|
+
- lib/dbwatcher/services/mermaid_syntax/flowchart_builder.rb
|
276
|
+
- lib/dbwatcher/services/mermaid_syntax/sanitizer.rb
|
277
|
+
- lib/dbwatcher/services/mermaid_syntax_builder.rb
|
186
278
|
- lib/dbwatcher/services/query_filter_processor.rb
|
187
279
|
- lib/dbwatcher/services/table_statistics_collector.rb
|
188
280
|
- lib/dbwatcher/sql_logger.rb
|