Class: Archsight::Documentation

Inherits:
Object
  • Object
show all
Defined in:
lib/archsight/documentation.rb

Overview

Documentation generates markdown documentation for architecture resources

Constant Summary collapse

LAYER_ORDER =

Layer display order (top to bottom)

%w[motivation strategy business application technology].freeze
LAYER_NAMES =

Layer display names

{
  "motivation" => "Motivation Layer",
  "strategy" => "Strategy Layer",
  "business" => "Business Layer",
  "application" => "Application Layer",
  "technology" => "Technology Layer"
}.freeze
EXCLUDED_KINDS =

Resource kinds to exclude from the diagram

%w[View].freeze

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.mermaid_cacheObject

Returns the value of attribute mermaid_cache.



27
28
29
# File 'lib/archsight/documentation.rb', line 27

def mermaid_cache
  @mermaid_cache
end

Class Method Details

.build_mermaid_diagramObject

Build the mermaid diagram from resource definitions Layer colors are defined in CSS (public/css/mermaid-layers.css)



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/archsight/documentation.rb', line 45

def build_mermaid_diagram
  lines = []
  lines << "flowchart TB"

  # Group resources by layer (excluding certain kinds)
  resources_by_layer = Hash.new { |h, k| h[k] = [] }
  Archsight::Resources.each do |kind_name|
    next if EXCLUDED_KINDS.include?(kind_name.to_s)

    klass = Archsight::Resources.const_get(kind_name)
    layer = klass.layer
    next unless LAYER_ORDER.include?(layer) # Skip resources in unlisted layers

    resources_by_layer[layer] << kind_name.to_s
  end

  # Generate subgraphs for each layer in order
  LAYER_ORDER.each do |layer|
    next unless resources_by_layer.key?(layer)

    kinds = resources_by_layer[layer].sort
    next if kinds.empty?

    lines << ""
    lines << "    subgraph #{layer.capitalize}[\"#{LAYER_NAMES[layer]}\"]"
    kinds.each do |kind|
      lines << "        #{kind}:::#{layer}"
    end
    lines << "    end"
  end

  # Collect all relations and deduplicate
  relations = collect_relations
  lines << ""
  relations.each do |from_kind, verb, to_kind|
    lines << "    #{from_kind} -->|#{verb}| #{to_kind}"
  end

  # Add click handlers for each kind
  lines << ""
  all_kinds = resources_by_layer.values.flatten
  all_kinds.sort.each do |kind_name|
    lines << "    click #{kind_name} \"/kinds/#{kind_name}\""
  end

  lines.join("\n")
end

.clear_cacheObject

Clear the mermaid cache (call when resources change)



39
40
41
# File 'lib/archsight/documentation.rb', line 39

def clear_cache
  @mermaid_cache = nil
end

.collect_relationsArray<Array>

Collect all unique relations from resource definitions

Returns:

  • (Array<Array>)

    Array of [from_kind, verb, to_kind] tuples



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/archsight/documentation.rb', line 95

def collect_relations
  relations = []
  seen = Set.new

  Archsight::Resources.each do |kind_name|
    # Skip excluded kinds
    next if EXCLUDED_KINDS.include?(kind_name.to_s)

    klass = Archsight::Resources.const_get(kind_name)
    # Skip kinds not in a displayed layer
    next unless LAYER_ORDER.include?(klass.layer)

    klass.relations.each do |verb, _relation_kind, target_klass|
      # Skip relations to excluded kinds
      next if EXCLUDED_KINDS.include?(target_klass.to_s)

      key = "#{kind_name}|#{verb}|#{target_klass}"
      next if seen.include?(key)

      seen.add(key)
      relations << [kind_name.to_s, verb.to_s.delete_prefix(":"), target_klass.to_s]
    end
  end

  relations.sort_by { |from, verb, to| [from, to, verb] }
end

.format_values(annotation) ⇒ Object



160
161
162
163
164
165
166
167
168
# File 'lib/archsight/documentation.rb', line 160

def format_values(annotation)
  if annotation.enum
    annotation.enum.join(", ")
  elsif annotation.type
    annotation.type.to_s.split("::").last
  else
    "-"
  end
end

.generate(kind_name) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/archsight/documentation.rb', line 122

def generate(kind_name)
  klass = Archsight::Resources[kind_name.to_s]
  raise "Unknown resource kind '#{kind_name}'" unless klass

  md = []
  md << "# #{kind_name}\n"
  md << klass.description if klass.description
  md << "\n## Annotations\n"
  md << generate_annotations_table(klass)
  md << "\n## Relations\n"
  md << generate_relations_table(klass)
  md << "\n## Example\n"
  md << "```yaml\n#{Archsight::Template.generate(kind_name)}```"
  md.compact.join("\n")
end

.generate_annotations_table(klass) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/archsight/documentation.rb', line 138

def generate_annotations_table(klass)
  annotations = klass.annotations.reject(&:pattern?)
  return "_No annotations defined._" if annotations.empty?

  rows = ["| Annotation | Description | Values |", "|------------|-------------|--------|"]
  annotations.each do |a|
    values = format_values(a)
    rows << "| `#{a.key}` | #{a.description || "-"} | #{values} |"
  end
  rows.join("\n")
end

.generate_mermaid_diagramString

Generate mermaid flowchart diagram showing all resource types and relationships Results are cached for performance

Returns:

  • (String)

    Mermaid flowchart diagram



32
33
34
35
36
# File 'lib/archsight/documentation.rb', line 32

def generate_mermaid_diagram
  return @mermaid_cache if @mermaid_cache

  @mermaid_cache = build_mermaid_diagram
end

.generate_relations_table(klass) ⇒ Object



150
151
152
153
154
155
156
157
158
# File 'lib/archsight/documentation.rb', line 150

def generate_relations_table(klass)
  return "_No relations defined._" if klass.relations.empty?

  rows = ["| Relation | Target | Kind |", "|----------|--------|------|"]
  klass.relations.each do |verb, kind, target_klass|
    rows << "| #{verb} | #{target_klass} | #{kind} |"
  end
  rows.join("\n")
end