eco-helpers 2.5.3 → 2.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adb24d7f2036b028bdd81302479211ea745e82abdb6b3a69afa2253e3f8fe444
4
- data.tar.gz: 4d149fa100a5a661e4b019aa601c0da3af051ba6e019c77e22b6599c312a4fcb
3
+ metadata.gz: 444bec4cd18402a38eff718340932ca7d72c9959b865805964b0ec9787d94636
4
+ data.tar.gz: 97291544f70b525781d81f168ffc86c1d960151e53535a540ac1b7824b9eaf28
5
5
  SHA512:
6
- metadata.gz: 8583dc7689de13744421db380f3193072f754091a1db6434010568907ff2f4e39d5ed3146b045ab47632cdf0bc5bc8c7e3fe326be466e7b4926f8c8c41344b31
7
- data.tar.gz: b34c886f7cde59854838a087fcb10442f14835a87bf3a264534a4a4641a3a1ca2b302352a920f37536cb0686a213ce7d2d06949c2c2bc89e31f3c8e7650ab32e
6
+ metadata.gz: 02360de987395d801aa1b1fb659dd4b6011c317a21058be33c3283b3a2856c69db519baf6eb85a022f7a2c7c4e826861b108c2cf09aefad3ca57b32d53b45c72
7
+ data.tar.gz: 402c880d701446c072f6534d4df35b2a104704dc79480e37e5033101df63a8b10baa25257911af1cc84994efe05744b15c608798dbc1637ad268811ca2d7d926
data/CHANGELOG.md CHANGED
@@ -1,7 +1,23 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
- ## [2.5.3] - 2023-07-xx
4
+ ## [2.5.5] - 2023-07-xx
5
+
6
+ ### Added
7
+ ### Changed
8
+ ### Fixed
9
+
10
+ ## [2.5.4] - 2023-07-27
11
+
12
+ ### Added
13
+ - SFTP case helpers: `Eco::API::UseCases::GraphQL::Utils::Sftp`
14
+ - `Eco::Data::Locations::NodeDiff` and `Eco::Data::Locations::NodeDiff::NodeDiffs`
15
+ - Aim to identify changes in the locations structure
16
+
17
+ ### Changed
18
+ - Some internal tidy up in `Eco::API::UseCases::GraphQL`
19
+
20
+ ## [2.5.3] - 2023-07-19
5
21
 
6
22
  ### Added
7
23
  - _GraphQL base case_ for **locations structure update**.
@@ -52,7 +68,6 @@ All notable changes to this project will be documented in this file.
52
68
  - `Eco::API::Session::Config::Workflow#exit_handle`
53
69
  - Allows to define a callback on `SystemExit` (`exit` call).
54
70
 
55
- ### Changed
56
71
  ### Fixed
57
72
  - `Eco::API::Session::Config::Workflow` on `SystemExit` preserve original exit `status` value (i.e. `0`, `1`)
58
73
  - It was changing an `exit 1` to be an `exit 0`
@@ -180,8 +180,8 @@ module Eco
180
180
 
181
181
  # Returns a plain list form of hash nodes.
182
182
  # @return [Array[Hash]] where `Hash` is a plain `node`
183
- def as_nodes_json
184
- all_nodes.map {|nd| nd.as_json(include_children: false)}
183
+ def as_nodes_json(&block)
184
+ all_nodes.map {|nd| nd.as_json(include_children: false, &block)}
185
185
  end
186
186
 
187
187
  # @return [Boolean] `true` if there are tags in the node, `false` otherwise.
@@ -0,0 +1,15 @@
1
+ module Eco::API::UseCases::GraphQL::Helpers::Base
2
+ # Basic stuff you would need in any use case
3
+ module CaseEnv
4
+ include Eco::Language::AuxiliarLogger
5
+ attr_reader :session, :options
6
+
7
+ def config
8
+ session.config
9
+ end
10
+
11
+ def simulate?
12
+ options.dig(:simulate)
13
+ end
14
+ end
15
+ end
@@ -1,20 +1,12 @@
1
1
  module Eco::API::UseCases::GraphQL::Helpers
2
2
  module Base
3
- include Eco::Language::AuxiliarLogger
4
- attr_reader :session, :options
3
+ require_relative 'base/case_env'
4
+ include Eco::API::UseCases::GraphQL::Helpers::Base::CaseEnv
5
5
 
6
6
  def graphql
7
7
  @graphql ||= session.api(version: :graphql)
8
8
  end
9
9
 
10
- def config
11
- session.config
12
- end
13
-
14
- def simulate?
15
- options.dig(:simulate)
16
- end
17
-
18
10
  # Keep a copy of the requests/responses for future reference
19
11
  def backup(data, type:)
20
12
  dry_run = simulate? ? "_dry_run" : ""
@@ -24,7 +16,7 @@ module Eco::API::UseCases::GraphQL::Helpers
24
16
  end
25
17
 
26
18
  def exit_error(msg)
27
- logger.error(msg)
19
+ log(:error) { msg }
28
20
  exit(1)
29
21
  end
30
22
  end
@@ -3,17 +3,25 @@ module Eco::API::UseCases::GraphQL::Helpers::Location
3
3
  include Eco::Language::AuxiliarLogger
4
4
  include Eco::API::UseCases::GraphQL::Helpers::Location::Base
5
5
 
6
- # Prevents each request from timing out
7
- COMMANDS_PER_PAGE = 45
8
- # Whether to stop or continue on command fail
9
- FORCE_CONTINUE = false
6
+ DEFAULT_COMMANDS_PER_PAGE = 45
7
+ DEFAULT_FORCE_CONTINUE = false
10
8
 
9
+ # Prevents each request from timing out
11
10
  def commands_per_page
12
- self.class::COMMANDS_PER_PAGE
11
+ if self.class.const_defined?(:COMMANDS_PER_PAGE)
12
+ self.class::COMMANDS_PER_PAGE
13
+ else
14
+ DEFAULT_COMMANDS_PER_PAGE
15
+ end
13
16
  end
14
17
 
18
+ # Whether to stop or continue on command fail
15
19
  def force_continue?
16
- self.class::FORCE_CONTINUE
20
+ if self.class.const_defined?(:FORCE_CONTINUE)
21
+ self.class::FORCE_CONTINUE
22
+ else
23
+ DEFAULT_FORCE_CONTINUE
24
+ end
17
25
  end
18
26
 
19
27
  # With given the commands, it generates the input of the endpoint mutation.
@@ -0,0 +1,74 @@
1
+ module Eco::API::UseCases::GraphQL::Utils
2
+ module Sftp
3
+ include Eco::API::UseCases::GraphQL::Helpers::Base::CaseEnv
4
+
5
+
6
+ def remote_subfolder
7
+ nil
8
+ end
9
+
10
+ def remote_folder(subfolder = remote_subfolder)
11
+ "#{sftp_config.remote_folder}/#{subfolder || ''}"
12
+ end
13
+
14
+ def sftp_group_id
15
+ if self.class.const_defined?(:SFTP_GROUP)
16
+ self.class.const_get(:TARGET_STRUCTURE_ID)
17
+ elsif group_id = options.dig(:sftp, :group)
18
+ group_id
19
+ end
20
+ end
21
+
22
+ def upload(local_file, remote_folder: self.remote_folder, gid: sftp_group_id)
23
+ return false unless local_file && File.exists?(local_file)
24
+ dest_file = "#{remote_folder}/#{File.basename(local_file)}"
25
+ res = sftp_session.upload!(local_file, dest_file)
26
+ attrs = sftp_session.stat!(dest_file)
27
+ if gid && gid != attrs.gid
28
+ stat_res = sftp_session.setstat!(dest_file, {permissions: 0660, uid: attrs.uid, gid: gid})
29
+ end
30
+ logger.info("Uploaded '#{local_file}' (#{res})")
31
+ end
32
+
33
+ def ensure_remote_empty
34
+ files = with_remote_files
35
+ unless files.empty?
36
+ msg = "There are still files in the remote folder that will be deleted: '#{remote_folder}':\n"
37
+ msg += " • " + files.map do |file|
38
+ file.longname
39
+ end.join("\n • ") + "\n"
40
+ session.prompt_user("Do you want to proceed to delete? (Y/n):", explanation: msg, default: "Y", timeout: 3) do |response|
41
+ if response.upcase.start_with?("Y")
42
+ files.each do |file|
43
+ remote_full_path = to_remote_path(file.name)
44
+ res = sftp_session.remove(remote_full_path)
45
+ logger.info("Deleted remote file: '#{remote_full_path}' (#{res})")
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ def with_remote_files
53
+ sftp.files(remote_folder).each do |remote_file|
54
+ yield(remote_file) if block_given?
55
+ end
56
+ end
57
+
58
+ def to_remote_path(file, subfolder: nil)
59
+ remote_folder(subfolder) + "/" + file
60
+ end
61
+
62
+ def sftp_config
63
+ session.config.sftp
64
+ end
65
+
66
+ def sftp_session
67
+ sftp.sftp_session
68
+ end
69
+
70
+ def sftp
71
+ session.sftp
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,6 @@
1
+ module Eco::API::UseCases::GraphQL
2
+ module Utils
3
+ end
4
+ end
5
+
6
+ require_relative 'utils/sftp'
@@ -8,5 +8,6 @@ module Eco
8
8
  end
9
9
 
10
10
  require_relative 'graphql/helpers'
11
+ require_relative 'graphql/utils'
11
12
  require_relative 'graphql/base'
12
13
  require_relative 'graphql/samples'
@@ -75,11 +75,11 @@ module Eco
75
75
  Dir.exist?(path) || Dir.exist?(File.expand_path(path))
76
76
  end
77
77
 
78
- def timestamp(timestamp_pattern = DEFAULT_TIMESTAMP_PATTERN)
79
- Time.now.strftime(timestamp_pattern)
78
+ def timestamp(timestamp_pattern = DEFAULT_TIMESTAMP_PATTERN, date = Time.now)
79
+ date.strftime(timestamp_pattern)
80
80
  end
81
81
 
82
- def timestamp_file(filename, timestamp_pattern = DEFAULT_TIMESTAMP_PATTERN)
82
+ def timestamp_file(filename, timestamp_pattern =DEFAULT_TIMESTAMP_PATTERN)
83
83
  file_pattern = Eco::Data::Files::FilePattern.new(filename)
84
84
  file_pattern.resolve(start: timestamp(timestamp_pattern) + '_')
85
85
  end
@@ -3,47 +3,16 @@ module Eco
3
3
  module Hashes
4
4
  class ArrayDiff
5
5
  extend Eco::Language::Models::ClassHelpers
6
-
7
- class << self
8
- def key(value = nil)
9
- return @key unless value
10
- @key = value.to_s
11
- end
12
-
13
- def key?
14
- !!@key
15
- end
16
-
17
- def compare(*attrs)
18
- compared_attrs.push(*attrs.map(&:to_s)).uniq!
19
- end
20
-
21
- def case_sensitive(value = nil)
22
- @case_sensitive = false unless instance_variable_defined?(:@case_sensitive)
23
- return @case_sensitive unless value
24
- @case_sensitive = !!value
25
- end
26
-
27
- def case_sensitive?
28
- !!@case_sensitive
29
- end
30
-
31
- def compared_attrs
32
- @compared_attrs ||= []
33
- @compared_attrs
34
- end
35
- end
6
+ # We can change the `DiffResult` class (items)
7
+ class_resolver :diff_result_class, "Eco::Data::Hash::DiffResult"
36
8
 
37
9
  include Eco::Language::AuxiliarLogger
38
10
 
39
11
  attr_reader :source1, :source2
40
12
  attr_reader :src_h1, :src_h2
41
13
 
42
- class_resolver :diff_result_class, "Eco::Data::Hash::DiffResult"
43
-
44
- def initialize(source1, source2, logger: nil, **kargs)
14
+ def initialize(source1, source2, logger: nil)
45
15
  @logger = logger if logger
46
- @options = kargs
47
16
  @source1 = source1
48
17
  @source2 = source2
49
18
  @src_h1 = by_key(source1)
@@ -67,14 +36,11 @@ module Eco
67
36
  !diffs.empty?
68
37
  end
69
38
 
39
+ # All the items that contain the diff of a node.
40
+ # @return [Array<Eco::Data::Hash::DiffResult>]
70
41
  def source_results
71
42
  @source_results ||= paired_sources.each_with_object([]) do |(src1, src2), res|
72
- args = {
73
- key: key,
74
- compare: compared_attrs,
75
- case_sensitive: case_sensitive?
76
- }
77
- res << diff_result_class.new(src1, src2, **args)
43
+ res << diff_result_class.new(src1, src2)
78
44
  end
79
45
  end
80
46
 
@@ -91,35 +57,23 @@ module Eco
91
57
  all_keys.map {|key| [src_h1[key], src_h2[key]]}
92
58
  end
93
59
 
60
+ # @return [String] the `key` attribute of `diff_result_class`
94
61
  def key
95
- @key ||= options_or(:key) do
96
- self.class.key
97
- end.tap do |k|
98
- raise "missing main key attr to pair records. Given: #{k}" unless k.is_a?(String)
62
+ diff_result_class.key.tap do |k|
63
+ raise "#{diff_result_class}: missing main key attr to pair records. Given: #{k}" unless k.is_a?(String)
99
64
  end
100
65
  end
101
66
 
102
67
  def case_sensitive?
103
- @case_sensitive ||= options_or(:case_sensitive) { self.class.case_sensitive? }
68
+ diff_result_class.case_sensitive?
104
69
  end
105
70
 
106
71
  def compared_attrs
107
- @compared_attrs ||= options_or(:compared_attrs) do
108
- self.class.compared_attrs
109
- end.yield_self do |attrs|
110
- raise "compared_attrs should be an array" unless attrs.is_a?(Array)
111
- attrs.map(&:to_s)
112
- end
72
+ diff_result_class.compared_attrs.map(&:to_s)
113
73
  end
114
74
 
115
75
  private
116
76
 
117
- def options_or(opt)
118
- opt = opt.to_sym
119
- return @options[opt] if @options.key?(opt)
120
- yield
121
- end
122
-
123
77
  def symbolize_keys(hash)
124
78
  hash.each_with_object({}) do |(k, v), h|
125
79
  h[k.to_sym] = v
@@ -0,0 +1,52 @@
1
+ module Eco
2
+ module Data
3
+ module Hashes
4
+ module DiffMeta
5
+ class << self
6
+ def included(base)
7
+ super(base)
8
+ base.extend ClassMethods
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ # @param value [String, NilClass]
14
+ # @return [String] the attribute that is key of the node diff elements.
15
+ def key(value = nil)
16
+ return @key unless value
17
+ @key = value.to_s
18
+ end
19
+
20
+ # @return [Boolean] is there a `key` attribute defined?
21
+ def key?
22
+ !!@key
23
+ end
24
+
25
+ # @param attrs [Array<Symbol>, Array<String>]
26
+ # @return [Array<String>] the comparable attributes
27
+ def compare(*attrs)
28
+ compared_attrs.push(*attrs.map(&:to_s)).uniq!
29
+ compared_attrs
30
+ end
31
+
32
+ # Whether or not the diff calc of a node should be done case sensitive or insensitive.
33
+ def case_sensitive(value = nil)
34
+ @case_sensitive = false unless instance_variable_defined?(:@case_sensitive)
35
+ return @case_sensitive unless value
36
+ @case_sensitive = !!value
37
+ end
38
+
39
+ # @return [Boolean] are comparisons of values done case sensitive?
40
+ def case_sensitive?
41
+ !!@case_sensitive
42
+ end
43
+
44
+ # @return [Array<String>] the comparable attributes
45
+ def compared_attrs
46
+ @compared_attrs ||= []
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -2,19 +2,32 @@ module Eco
2
2
  module Data
3
3
  module Hashes
4
4
  class DiffResult
5
- attr_reader :key
5
+ extend Eco::Language::Models::ClassHelpers
6
+ include Eco::Data::Hashes::DiffMeta
7
+
8
+ inheritable_class_vars :key, :compared_attrs, :case_sensitive
9
+
6
10
  attr_reader :src1, :src2
7
11
 
8
- # @param compare [Array<String>, sym]
9
- # - `:all` compares the matching attrs between both hashes only
10
- def initialize(src1, src2, key:, compare: :all, case_sensitive: false)
11
- @key = key
12
- @compare = compare
13
- @case_sensitive = case_sensitive
12
+ def initialize(src1, src2)
14
13
  @src1 = src1
15
14
  @src2 = src2
16
15
  end
17
16
 
17
+ def key
18
+ self.class.key
19
+ end
20
+
21
+ def case_sensitive?
22
+ self.class.case_sensitive?
23
+ end
24
+
25
+ def dup(src1: nil, src2: nil)
26
+ src1 ||= self.src1
27
+ src2 ||= self.src2
28
+ self.class.new(src1.dup, src2.dup)
29
+ end
30
+
18
31
  def new?
19
32
  !src1 && !!src2
20
33
  end
@@ -27,35 +40,39 @@ module Eco
27
40
  !new? && !del? && diff?
28
41
  end
29
42
 
43
+ # @note `diff_attrs` may not include the `key` attribute
44
+ # This is always included via `new?` (new key value) and `del?` (missing key value)
45
+ # @return [Boolean] was there any change?
30
46
  def diff?
31
47
  new? || del? || !diff_attrs.empty?
32
48
  end
33
49
 
34
- # Is the key attr value changing?
50
+ # Is the `key` attr value changing?
35
51
  def key?
36
52
  !(new? || del?) && diff_attr?(key)
37
53
  end
38
54
 
55
+ # Is `attr` part of the attributes that change?
39
56
  def diff_attr?(attr)
40
57
  return true if new?
41
58
  return true if del?
42
59
  diff_attrs.include?(attr.to_s)
43
60
  end
44
61
 
62
+ # @return [Value] the current value of `attr` (in `src2`)
45
63
  def attr(attr)
46
64
  return nil unless src2
47
65
  src2[attr.to_s]
48
66
  end
49
67
 
68
+ # @return [Value] the previous value of `attr` (in `src1`)
50
69
  def attr_prev(attr)
51
70
  return nil unless src1
52
71
  src1[attr.to_s]
53
72
  end
54
73
 
55
- def previous(attr)
56
- src1 && src1[attr.to_s]
57
- end
58
-
74
+ # @note the `key` attribute will always be added (even if there's no change)
75
+ # @return [Hash] hash with the differences as per `src2`
59
76
  def diff_hash
60
77
  target_attrs = [key] | compared_attrs
61
78
  return src2.slice(*target_attrs) if new?
@@ -63,12 +80,14 @@ module Eco
63
80
  src2.slice(key, *diff_attrs)
64
81
  end
65
82
 
83
+ # @return [Array<Symbol>] hash with the differences as per `src2`
66
84
  def diff_attrs
67
85
  @diff_attrs ||= comparable_attrs.each_with_object([]) do |attr, out|
68
86
  out << attr unless eq?(src1[attr], src2[attr])
69
87
  end
70
88
  end
71
89
 
90
+ # @return [Boolean] whether `val1` is equal to `val2`
72
91
  def eq?(val1, val2)
73
92
  return true if val1 == val2
74
93
  return false if case_sensitive?
@@ -76,25 +95,18 @@ module Eco
76
95
  val1.upcase == val2.upcase
77
96
  end
78
97
 
79
- def case_sensitive?
80
- !!@case_sensitive
81
- end
82
-
98
+ # @note when is `new?` or to be deleted (`del?`), it returns empty array.
99
+ # @return [Array<String>] the set of attributes that are comparable in this instance.
83
100
  def comparable_attrs
84
101
  return [] if new? || del?
85
102
  compared_attrs
86
103
  end
87
104
 
105
+ # @return [Array<String>] the set of attributes that are comparable in this class.
88
106
  def compared_attrs
89
- return @compared_attrs if instance_variable_defined?(:@compared_attrs)
90
- @compared_attrs = \
91
- if @compare == :all
92
- src1.keys & src2.keys
93
- elsif @compare.is_a?(Array)
94
- @compare.map(&:to_s)
95
- else
96
- raise "Expecting 'compare' to be sym (:all) or Array<String>. Given: #{@compare.class}"
97
- end
107
+ comp_attrs = self.class.compared_attrs.map(&:to_s).uniq
108
+ return comp_attrs unless comp_attrs.empty?
109
+ (src1&.keys || []) & (src2&.keys || [])
98
110
  end
99
111
  end
100
112
  end
@@ -5,5 +5,6 @@ module Eco
5
5
  end
6
6
  end
7
7
 
8
+ require_relative 'hashes/diff_meta'
8
9
  require_relative 'hashes/diff_result'
9
10
  require_relative 'hashes/array_diff'
@@ -0,0 +1,46 @@
1
+ class Eco::Data::Locations::NodeDiff
2
+ module Accessors
3
+ class << self
4
+ def included(base)
5
+ super(base)
6
+ base.extend Eco::Language::Models::ClassHelpers
7
+ base.extend ClassMethods
8
+ base.inheritable_class_vars :exposed_attrs
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ # Creates the defined accessor attributes against `NodeDiff`
14
+ # It also creates a method with question mark that evaluates true if **any** the attr changed.
15
+ # @note the defined attributes are expected to be the keys within
16
+ # the source Hashes that are being compared.
17
+ # @note accessing `src1` (prev) attributes, will have it's method as `prev_[attrName]`
18
+ def attr_expose(*attrs)
19
+ attrs.each do |attr|
20
+ meth = attr.to_sym
21
+ methp = "prev_#{meth}".to_sym
22
+ methq = "diff_#{meth}?".to_sym
23
+
24
+ define_method meth do
25
+ attr(meth)
26
+ end
27
+
28
+ define_method methp do
29
+ attr_prev(meth)
30
+ end
31
+
32
+ exposed_attrs |= [meth]
33
+
34
+ define_method methq do
35
+ diff_attr?(meth)
36
+ end
37
+ end
38
+ end
39
+
40
+ # Keeps track on what attributes have been exposed.
41
+ def exposed_attrs
42
+ @exposed_attrs ||= []
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,90 @@
1
+ class Eco::Data::Locations::NodeDiff
2
+ # Adjusts ArrayDiff for Nodes diffs in a location structure
3
+ class NodesDiff < Eco::Data::Hashes::ArrayDiff
4
+ extend Eco::Data::Locations::NodeDiff::Selectors
5
+
6
+ SELECTORS = %i[id name id_name insert unarchive update move archive]
7
+ selector *SELECTORS
8
+
9
+ class_resolver :diff_result_class, Eco::Data::Locations::NodeDiff
10
+ attr_reader :original_tree
11
+
12
+ def initialize(*args, original_tree:, **kargs, &block)
13
+ super(*args, **kargs, &block)
14
+ @original_tree = original_tree
15
+ end
16
+
17
+ def diffs
18
+ @diffs ||= super.select do |res|
19
+ res.unarchive? || res.id_name? || res.insert? || res.move? || res.archive?
20
+ end
21
+ end
22
+
23
+ def diffs_details
24
+ section = '#' * 10
25
+ msg = ''
26
+ if insert?
27
+ msg << " #{section} I N S E R T S #{section}\n"
28
+ msg << insert.map {|d| d.diff_hash.pretty_inspect}.join('')
29
+ end
30
+
31
+ if update?
32
+ msg << "\n #{section} U P D A T E S #{section}\n"
33
+ update.each do |d|
34
+ flags = ''
35
+ #flags << 'i' if d.id?
36
+ flags << 'n' if d.diff_name?
37
+ flags << 'm' if d.move?
38
+ flags << 'u' if d.unarchive?
39
+ msg << "<< #{flags} >> "
40
+ msg << d.diff_hash.pretty_inspect
41
+ end
42
+ end
43
+
44
+ if archive?
45
+ msg << "\n #{section} A R C H I V E S #{section}\n"
46
+ msg << archive.map {|d| d.diff_hash.pretty_inspect}.join('')
47
+ end
48
+
49
+ msg
50
+ end
51
+
52
+ def diffs_summary
53
+ return "There were no differences identified" if diffs.empty?
54
+ msg = "Identified #{diffs.count} differences:\n"
55
+ msg << when_present(insert, '') do |count|
56
+ " • #{count} nodes to insert\n"
57
+ end
58
+ msg << when_present(update, '') do |count|
59
+ " • #{count} nodes to update\n"
60
+ end
61
+ # msg << when_present(id, '') do |count|
62
+ # " • #{count} nodes to change id\n"
63
+ # end
64
+ msg << when_present(name, '') do |count|
65
+ " • #{count} nodes to change name\n"
66
+ end
67
+ msg << when_present(move, '') do |count|
68
+ " • #{count} nodes to move\n"
69
+ end
70
+ msg << when_present(unarchive, '') do |count|
71
+ " • #{count} nodes to unarchive\n"
72
+ end
73
+ msg << when_present(archive, '') do |count|
74
+ " • #{count} nodes to archive\n"
75
+ end
76
+ msg
77
+ end
78
+
79
+ private
80
+
81
+ def when_present(list, default = nil)
82
+ count = list.count
83
+ if count > 0
84
+ yield(count)
85
+ else
86
+ default
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,20 @@
1
+ class Eco::Data::Locations::NodeDiff
2
+ module Selectors
3
+ # Creates selector methods on `diffs` (nodes that changed)
4
+ # It also creates a method with question mark that evaluates true if **any** diff matches.
5
+ # @note the selector method name with a question mark should exist in the `diff_result_class`
6
+ def selector(*attrs)
7
+ attrs.each do |attr|
8
+ meth = attr.to_sym
9
+ methq = "#{meth}?".to_sym
10
+ define_method meth do
11
+ diffs.select(&methq)
12
+ end
13
+
14
+ define_method methq do
15
+ diffs.any(&methq)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,55 @@
1
+ module Eco::Data::Locations
2
+ # Differences between node before and after
3
+ # @note this works with `Hash` object where basic keys are:
4
+ # - `nodeId`
5
+ # - `name`
6
+ # - `parentId`
7
+ # - `archived`
8
+ # @note other properties can be part of the `Hash` although
9
+ # they may not influence the results.
10
+ class NodeDiff < Eco::Data::Hashes::DiffResult
11
+ require_relative 'node_diff/accessors'
12
+ require_relative 'node_diff/selectors'
13
+ require_relative 'node_diff/nodes_diff'
14
+
15
+ include Eco::Data::Locations::NodeDiff::Accessors
16
+
17
+ key :nodeId
18
+ compare :parentId, :name, :archived
19
+ case_sensitive false
20
+
21
+ attr_expose :nodeId, :name, :parentId, :archived
22
+
23
+ alias_method :insert?, :new?
24
+
25
+ alias_method :diff_name_src?, :diff_name?
26
+ # Has the property `name` changed?
27
+ def diff_name?
28
+ diff_name_src? && update?
29
+ end
30
+ alias_method :name?, :diff_name?
31
+ alias_method :id? , :diff_name? # currently a change of name is a change of id (tag)
32
+ #alias_method :id? , :key?
33
+ #alias_method :nodeId? , :id?
34
+
35
+ # Has any of `id` or `name` properties changed?
36
+ def id_name?
37
+ id? || diff_name?
38
+ end
39
+
40
+ # Has the parent id changed?
41
+ def move?
42
+ update? && diff_parentId?
43
+ end
44
+
45
+ # Has the `archived` property changed and it was `true`?
46
+ def unarchive?
47
+ !archived && update? && diff_archived?
48
+ end
49
+
50
+ # Has the `archived` property changed and it was `false`?
51
+ def archive?
52
+ !prev_archived && (del? || archived)
53
+ end
54
+ end
55
+ end
@@ -18,13 +18,10 @@ module Eco::Data::Locations
18
18
 
19
19
  attr_accessor :parentId
20
20
 
21
- def nodeId
22
- id
23
- end
24
-
25
21
  def id
26
22
  tag.upcase
27
23
  end
24
+ alias_method :nodeId, :id
28
25
 
29
26
  def name
30
27
  tag
@@ -17,6 +17,8 @@ module Eco::Data::Locations
17
17
  def id
18
18
  clean_id(super)
19
19
  end
20
+ # backwards compatibility
21
+ alias_method :tag, :id
20
22
 
21
23
  def name
22
24
  super || self.id
@@ -25,10 +27,5 @@ module Eco::Data::Locations
25
27
  def parentId
26
28
  self.parent_id
27
29
  end
28
-
29
- # backwards compatibility
30
- def tag
31
- id
32
- end
33
30
  end
34
31
  end
@@ -9,4 +9,5 @@ require_relative 'locations/convert'
9
9
  require_relative 'locations/node_base'
10
10
  require_relative 'locations/node_plain'
11
11
  require_relative 'locations/node_level'
12
+ require_relative 'locations/node_diff'
12
13
  require_relative 'locations/dsl'
data/lib/eco/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eco
2
- VERSION = "2.5.3"
2
+ VERSION = "2.5.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eco-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.3
4
+ version: 2.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Segura
@@ -592,6 +592,7 @@ files:
592
592
  - lib/eco/api/usecases/graphql/base.rb
593
593
  - lib/eco/api/usecases/graphql/helpers.rb
594
594
  - lib/eco/api/usecases/graphql/helpers/base.rb
595
+ - lib/eco/api/usecases/graphql/helpers/base/case_env.rb
595
596
  - lib/eco/api/usecases/graphql/helpers/location.rb
596
597
  - lib/eco/api/usecases/graphql/helpers/location/base.rb
597
598
  - lib/eco/api/usecases/graphql/helpers/location/command.rb
@@ -603,6 +604,8 @@ files:
603
604
  - lib/eco/api/usecases/graphql/samples/location/command/dsl.rb
604
605
  - lib/eco/api/usecases/graphql/samples/location/command/results.rb
605
606
  - lib/eco/api/usecases/graphql/samples/location/dsl.rb
607
+ - lib/eco/api/usecases/graphql/utils.rb
608
+ - lib/eco/api/usecases/graphql/utils/sftp.rb
606
609
  - lib/eco/api/usecases/ooze_cases.rb
607
610
  - lib/eco/api/usecases/ooze_cases/export_register_case.rb
608
611
  - lib/eco/api/usecases/ooze_samples.rb
@@ -670,6 +673,7 @@ files:
670
673
  - lib/eco/data/fuzzy_match/string_helpers.rb
671
674
  - lib/eco/data/hashes.rb
672
675
  - lib/eco/data/hashes/array_diff.rb
676
+ - lib/eco/data/hashes/diff_meta.rb
673
677
  - lib/eco/data/hashes/diff_result.rb
674
678
  - lib/eco/data/locations.rb
675
679
  - lib/eco/data/locations/convert.rb
@@ -681,6 +685,10 @@ files:
681
685
  - lib/eco/data/locations/node_base/serial.rb
682
686
  - lib/eco/data/locations/node_base/tag_validations.rb
683
687
  - lib/eco/data/locations/node_base/treeify.rb
688
+ - lib/eco/data/locations/node_diff.rb
689
+ - lib/eco/data/locations/node_diff/accessors.rb
690
+ - lib/eco/data/locations/node_diff/nodes_diff.rb
691
+ - lib/eco/data/locations/node_diff/selectors.rb
684
692
  - lib/eco/data/locations/node_level.rb
685
693
  - lib/eco/data/locations/node_level/builder.rb
686
694
  - lib/eco/data/locations/node_level/cleaner.rb