Module: Archsight::Editor
- Defined in:
- lib/archsight/editor.rb,
lib/archsight/editor/file_writer.rb,
lib/archsight/editor/content_hasher.rb
Overview
Editor handles building and validating resources for the web editor
Defined Under Namespace
Modules: ContentHasher, FileWriter
Class Method Summary collapse
-
.apply_block_scalar_style(node) ⇒ Object
Recursively apply literal block style for multiline strings in YAML AST.
-
.available_relations(kind) ⇒ Array<Array>
Get available relations for a resource kind.
-
.build_resource(kind:, name:, annotations: {}, relations: []) ⇒ Hash
Build a resource hash from form params.
-
.editable_annotations(kind) ⇒ Array<Archsight::Annotations::Annotation>
Get editable annotations for a resource kind Excludes pattern annotations, computed annotations, and annotations with editor: false.
-
.relation_name_for(kind, verb, target_class) ⇒ String?
Get relation name for a given verb and target class (for building spec).
-
.relation_verbs(kind) ⇒ Array<String>
Get unique verbs for a resource kind’s relations.
-
.target_class_for_relation(kind, verb, relation_name) ⇒ String?
Get target class name for a given verb and relation name (reverse lookup).
-
.target_kinds_for_verb(kind, verb) ⇒ Array<String>
Get valid target class names for a given verb (for UI display and instance lookup).
-
.to_yaml(resource_hash) ⇒ String
Generate YAML string from resource hash Uses custom YAML dump that formats multiline strings with literal block scalars.
-
.validate(kind, name:, annotations: {}) ⇒ Hash
Validate resource params using annotation definitions.
Class Method Details
.apply_block_scalar_style(node) ⇒ Object
Recursively apply literal block style for multiline strings in YAML AST
85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/archsight/editor.rb', line 85 def apply_block_scalar_style(node) case node when Psych::Nodes::Scalar if node.value.is_a?(String) # Normalize Windows/old Mac line endings to Unix style node.value = node.value.gsub("\r\n", "\n").gsub("\r", "\n") if node.value.include?("\r") # Use literal block style for multiline strings node.style = Psych::Nodes::Scalar::LITERAL if node.value.include?("\n") end when Psych::Nodes::Sequence, Psych::Nodes::Mapping, Psych::Nodes::Document, Psych::Nodes::Stream node.children.each { |child| apply_block_scalar_style(child) } end end |
.available_relations(kind) ⇒ Array<Array>
Get available relations for a resource kind
121 122 123 124 125 126 |
# File 'lib/archsight/editor.rb', line 121 def available_relations(kind) klass = Archsight::Resources[kind] return [] unless klass klass.relations end |
.build_resource(kind:, name:, annotations: {}, relations: []) ⇒ Hash
Build a resource hash from form params
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/archsight/editor.rb', line 20 def build_resource(kind:, name:, annotations: {}, relations: []) resource = { "apiVersion" => "architecture/v1alpha1", "kind" => kind, "metadata" => { "name" => name } } # Add annotations if any non-empty values exist filtered_annotations = filter_empty(annotations) resource["metadata"]["annotations"] = filtered_annotations unless filtered_annotations.empty? # Add spec with relations if any exist spec = build_spec(kind, relations) resource["spec"] = spec unless spec.empty? resource end |
.editable_annotations(kind) ⇒ Array<Archsight::Annotations::Annotation>
Get editable annotations for a resource kind Excludes pattern annotations, computed annotations, and annotations with editor: false
103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/archsight/editor.rb', line 103 def editable_annotations(kind) klass = Archsight::Resources[kind] return [] unless klass # Get all annotations except pattern annotations annotations = klass.annotations.reject(&:pattern?) # Filter out computed annotations computed_keys = klass.computed_annotations.map(&:key) annotations = annotations.reject { |a| computed_keys.include?(a.key) } # Filter out non-editable annotations annotations.reject { |a| a.editor == false } end |
.relation_name_for(kind, verb, target_class) ⇒ String?
Get relation name for a given verb and target class (for building spec)
153 154 155 156 157 158 159 160 |
# File 'lib/archsight/editor.rb', line 153 def relation_name_for(kind, verb, target_class) relation = available_relations(kind).find do |v, _, tc| v.to_s == verb.to_s && tc.to_s == target_class.to_s end return nil unless relation relation[1].to_s end |
.relation_verbs(kind) ⇒ Array<String>
Get unique verbs for a resource kind’s relations
131 132 133 |
# File 'lib/archsight/editor.rb', line 131 def relation_verbs(kind) available_relations(kind).map { |v, _, _| v.to_s }.uniq.sort end |
.target_class_for_relation(kind, verb, relation_name) ⇒ String?
Get target class name for a given verb and relation name (reverse lookup)
167 168 169 170 171 172 173 174 |
# File 'lib/archsight/editor.rb', line 167 def target_class_for_relation(kind, verb, relation_name) relation = available_relations(kind).find do |v, rn, _| v.to_s == verb.to_s && rn.to_s == relation_name.to_s end return nil unless relation relation[2].to_s end |
.target_kinds_for_verb(kind, verb) ⇒ Array<String>
Get valid target class names for a given verb (for UI display and instance lookup)
139 140 141 142 143 144 145 146 |
# File 'lib/archsight/editor.rb', line 139 def target_kinds_for_verb(kind, verb) # Relations structure is [verb, relation_name, target_class_name] available_relations(kind) .select { |v, _, _| v.to_s == verb.to_s } .map { |_, _, target_class| target_class.to_s } .uniq .sort end |
.to_yaml(resource_hash) ⇒ String
Generate YAML string from resource hash Uses custom YAML dump that formats multiline strings with literal block scalars
72 73 74 75 76 77 78 79 80 81 |
# File 'lib/archsight/editor.rb', line 72 def to_yaml(resource_hash) visitor = Psych::Visitors::YAMLTree.create visitor << resource_hash # Walk the AST and apply scalar style for multiline strings ast = visitor.tree apply_block_scalar_style(ast) ast.yaml(nil, line_width: 80) end |
.validate(kind, name:, annotations: {}) ⇒ Hash
Validate resource params using annotation definitions
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/archsight/editor.rb', line 45 def validate(kind, name:, annotations: {}) klass = Archsight::Resources[kind] errors = {} # Validate name if name.nil? || name.strip.empty? errors["name"] = ["Name is required"] elsif name =~ /\s/ errors["name"] = ["Name cannot contain spaces"] end # Validate annotations against their definitions klass.annotations.reject(&:pattern?).each do |ann| value = annotations[ann.key] next if value.nil? || value.to_s.strip.empty? ann_errors = ann.validate(value) errors[ann.key] = ann_errors if ann_errors.any? end { valid: errors.empty?, errors: errors } end |