eco-helpers 3.2.23 → 3.3.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +92 -39
  3. data/lib/eco/api/common/session/base_session.rb +4 -0
  4. data/lib/eco/api/common/session/environment.rb +5 -0
  5. data/lib/eco/api/custom/cli.rb +3 -0
  6. data/lib/eco/api/session/config/api.rb +33 -14
  7. data/lib/eco/api/usecases/CLAUDE.md +78 -0
  8. data/lib/eco/api/usecases/graphql/CLAUDE.md +120 -0
  9. data/lib/eco/api/usecases/graphql/compat/ooze_redirect.rb +13 -2
  10. data/lib/eco/api/usecases/graphql/helpers/CLAUDE.md +79 -0
  11. data/lib/eco/api/usecases/graphql/helpers/access_logs/base/reader.rb +59 -0
  12. data/lib/eco/api/usecases/graphql/helpers/access_logs/base.rb +17 -0
  13. data/lib/eco/api/usecases/graphql/helpers/access_logs.rb +7 -0
  14. data/lib/eco/api/usecases/graphql/helpers/base/connection_reader.rb +70 -0
  15. data/lib/eco/api/usecases/graphql/helpers/base/graphql_env.rb +6 -2
  16. data/lib/eco/api/usecases/graphql/helpers/base.rb +1 -0
  17. data/lib/eco/api/usecases/graphql/helpers/contractors/base/manager_settings.rb +64 -0
  18. data/lib/eco/api/usecases/graphql/helpers/contractors/base.rb +2 -0
  19. data/lib/eco/api/usecases/graphql/helpers/dashboards/base/reader.rb +30 -0
  20. data/lib/eco/api/usecases/graphql/helpers/dashboards/base.rb +20 -0
  21. data/lib/eco/api/usecases/graphql/helpers/dashboards.rb +7 -0
  22. data/lib/eco/api/usecases/graphql/helpers/pages/activities.rb +51 -0
  23. data/lib/eco/api/usecases/graphql/helpers/pages.rb +2 -1
  24. data/lib/eco/api/usecases/graphql/helpers.rb +2 -0
  25. data/lib/eco/api/usecases/graphql/samples/CLAUDE.md +76 -0
  26. data/lib/eco/api/usecases/graphql/samples/contractors/dsl.rb +16 -0
  27. data/lib/eco/api/usecases/graphql/samples/pages/CLAUDE.md +59 -0
  28. data/lib/eco/api/usecases/graphql/samples/pages/template/base.rb +46 -37
  29. data/lib/eco/api/usecases/graphql/samples/pages/template.rb +1 -1
  30. data/lib/eco/version.rb +1 -1
  31. metadata +22 -7
@@ -0,0 +1,17 @@
1
+ require_relative 'base/reader'
2
+
3
+ module Eco::API::UseCases::GraphQL::Helpers::AccessLogs
4
+ # System Access Logs helper mixin — NATIVE reader over `activityLogs`.
5
+ module Base
6
+ include Eco::API::UseCases::GraphQL::Helpers::Base
7
+
8
+ private
9
+
10
+ # Build a lazy reader over the org's system access logs (ActivityLogUnion).
11
+ # @see Reader#initialize for the supported filters.
12
+ # @return [Reader]
13
+ def access_logs(**filters)
14
+ Reader.new(graphql, **filters)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ module Eco::API::UseCases::GraphQL::Helpers
2
+ # NATIVE System Access Logs readers (currentOrganization.activityLogs).
3
+ module AccessLogs
4
+ end
5
+ end
6
+
7
+ require_relative 'access_logs/base'
@@ -0,0 +1,70 @@
1
+ module Eco::API::UseCases::GraphQL::Helpers::Base
2
+ # Shared substrate for NATIVE GraphQL connection readers.
3
+ #
4
+ # The gem's `Logic::QueryConnection` is already `Enumerable` and paginates lazily over
5
+ # `first`/`after` using `pageInfo.endCursor`/`hasNextPage` (see its `#each`). This mixin wraps
6
+ # that machinery behind a small, uniform reader surface so every native reader (access logs,
7
+ # page activities, dashboards, ...) exposes the same `each` / `to_a` / `first(n)` behaviour and
8
+ # a consistent `page_size` without re-implementing cursor pagination.
9
+ #
10
+ # A concrete reader supplies a `#query` (a gem query object, e.g.
11
+ # `graphql.currentOrganization.activityLogs`) and the per-call filter/argument hash via
12
+ # `#reader_params`. Everything else (lazy iteration, batching, materialising) is inherited.
13
+ module ConnectionReader
14
+ include Enumerable
15
+
16
+ # Default number of nodes fetched per network round-trip.
17
+ DEFAULT_PAGE_SIZE = 100
18
+
19
+ # Iterate over every node across all pages (lazy — one network page at a time).
20
+ # @yieldparam node [Object] a gem read model (e.g. Model::ActivityLog / Model::Activity).
21
+ # @return [Enumerator] when no block is given.
22
+ def each(&block)
23
+ return to_enum(:each) unless block
24
+
25
+ connection_query.each(**each_params, &block)
26
+ end
27
+
28
+ # Materialise a bounded number of nodes without draining the whole connection.
29
+ # @param limit [Integer, nil] maximum nodes to return; nil = all pages.
30
+ # @return [Array]
31
+ def to_a(limit: nil)
32
+ return super() if limit.nil?
33
+
34
+ take(limit)
35
+ end
36
+
37
+ # @return [Integer] nodes fetched per page.
38
+ def page_size
39
+ @page_size ||= DEFAULT_PAGE_SIZE
40
+ end
41
+
42
+ # @param size [Integer]
43
+ def page_size=(size)
44
+ @page_size = Integer(size)
45
+ end
46
+
47
+ private
48
+
49
+ # The gem query object to iterate (must respond to `#each(**kargs)` — i.e. a
50
+ # `Logic::QueryConnection`). Concrete readers MUST override.
51
+ # @return [Ecoportal::API::GraphQL::Logic::QueryConnection]
52
+ def connection_query
53
+ raise NotImplementedError, "#{self.class} must implement #connection_query"
54
+ end
55
+
56
+ # Per-call arguments (filters + page id + ...) merged into every page request.
57
+ # Concrete readers override to add their own filters. `first` defaults to `page_size`.
58
+ # @return [Hash]
59
+ def reader_params
60
+ {}
61
+ end
62
+
63
+ # Final kargs handed to the gem's `QueryConnection#each` — reader_params with a
64
+ # default `first`, and nils stripped so unset filters are not sent.
65
+ # @return [Hash]
66
+ def each_params
67
+ { first: page_size }.merge(reader_params).compact
68
+ end
69
+ end
70
+ end
@@ -6,8 +6,12 @@ module Eco::API::UseCases::GraphQL::Helpers::Base
6
6
  private
7
7
 
8
8
  def graphql
9
- msg = "The credentials or basic graphql config are missing for the active environment"
10
- raise msg unless session.api?(version: :graphql)
9
+ unless session.api?(version: :graphql)
10
+ missing = session.missing_api_params(version: :graphql)
11
+ msg = "The credentials or basic graphql config are missing for the active environment"
12
+ msg << " (missing params: #{missing.map {|param| ":#{param}"}.join(', ')})" if missing.any?
13
+ raise msg
14
+ end
11
15
 
12
16
  @graphql ||= session.api(version: :graphql)
13
17
  end
@@ -3,6 +3,7 @@ module Eco::API::UseCases::GraphQL::Helpers
3
3
  require_relative 'base/error_handling'
4
4
  require_relative 'base/case_env'
5
5
  require_relative 'base/graphql_env'
6
+ require_relative 'base/connection_reader'
6
7
 
7
8
  include CaseEnv
8
9
  include GraphQLEnv
@@ -0,0 +1,64 @@
1
+ module Eco::API::UseCases::GraphQL::Helpers::Contractors
2
+ module Base
3
+ # NATIVE contractor **write** helper — `updateContractorManagerSettings`.
4
+ #
5
+ # Drives the gem's `Builder::ContractorEntity#update_manager_settings` to set the
6
+ # organisation's contractor-manager auto-approval settings and whether contractor admins
7
+ # may add other admins.
8
+ #
9
+ # Guards (aligned with the repo's write discipline):
10
+ # - **dry-run / simulate:** when `simulate?` (or `dry_run:` is passed), NO mutation is sent;
11
+ # the intended input is logged and returned so callers can inspect it.
12
+ # - **-no-email:** honoured — when email is suppressed (`options.dig(:workflow, :no_email)`
13
+ # or an explicit `no_email:`), the helper does not emit its own success notification. The
14
+ # server-side mutation itself sends no member email for this settings change.
15
+ module ManagerSettings
16
+ include Eco::API::UseCases::GraphQL::Helpers::Base
17
+
18
+ private
19
+
20
+ # Update the org's contractor manager settings.
21
+ # @param cm_auto_approvals_settings [Hash, nil] AutoApprovalsInput
22
+ # ({ enabled:, approvalConditions: }). Required by the schema for a real update.
23
+ # @param allow_contractor_admins_to_add_admins [Boolean, nil]
24
+ # @param dry_run [Boolean, nil] force simulate for this call (in addition to `simulate?`).
25
+ # @param no_email [Boolean, nil] suppress this helper's own notification for this call.
26
+ # @return [Hash] when simulated: the intended input hash. Otherwise: the mutation payload.
27
+ def update_contractor_manager_settings(
28
+ cm_auto_approvals_settings: nil,
29
+ allow_contractor_admins_to_add_admins: nil,
30
+ dry_run: nil,
31
+ no_email: nil
32
+ )
33
+ input = {}
34
+ input[:cmAutoApprovalsSettings] = cm_auto_approvals_settings unless cm_auto_approvals_settings.nil?
35
+ unless allow_contractor_admins_to_add_admins.nil?
36
+ input[:allowContractorAdminsToAddAdmins] =
37
+ allow_contractor_admins_to_add_admins
38
+ end
39
+
40
+ if dry_run || simulate?
41
+ log(:info) { "[dry-run] updateContractorManagerSettings input: #{input}" }
42
+ return input
43
+ end
44
+
45
+ graphql.contractorEntity.update_manager_settings(input: input).tap do
46
+ notify_manager_settings_updated(input) unless suppress_email?(no_email)
47
+ end
48
+ end
49
+
50
+ # @return [Boolean] whether this helper's own notification email is suppressed.
51
+ def suppress_email?(no_email)
52
+ return true if no_email
53
+ return true if respond_to?(:options, true) && options.dig(:workflow, :no_email)
54
+
55
+ false
56
+ end
57
+
58
+ # Hook for a success notification (kept minimal; overridable). Logs by default.
59
+ def notify_manager_settings_updated(input)
60
+ log(:info) { "Updated contractor manager settings: #{input}" }
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,8 +1,10 @@
1
1
  require_relative 'base/load'
2
+ require_relative 'base/manager_settings'
2
3
 
3
4
  module Eco::API::UseCases::GraphQL::Helpers::Contractors
4
5
  module Base
5
6
  include Eco::API::UseCases::GraphQL::Helpers::Base
6
7
  include Load
8
+ include ManagerSettings
7
9
  end
8
10
  end
@@ -0,0 +1,30 @@
1
+ module Eco::API::UseCases::GraphQL::Helpers::Dashboards
2
+ module Base
3
+ # NATIVE reader over `currentOrganization.dashboardSearch` (MinimalDashboardConnection).
4
+ # Lazily paginates and yields `Model::MinimalDashboard` records.
5
+ #
6
+ # Use via `Helpers::Dashboards::Base#dashboards`:
7
+ # dashboards(query: 'safety').each { |d| ... }
8
+ # dashboards.to_a
9
+ class Reader
10
+ include Eco::API::UseCases::GraphQL::Helpers::Base::ConnectionReader
11
+
12
+ # @param graphql [Ecoportal::API::GraphQL] the active gem client.
13
+ # @param search_conf [Hash, nil] a `Search` input hash ({ query:, filters:, sorters: }).
14
+ def initialize(graphql, search_conf: nil)
15
+ @graphql = graphql
16
+ @search_conf = search_conf
17
+ end
18
+
19
+ private
20
+
21
+ def connection_query
22
+ @graphql.currentOrganization.dashboardSearch
23
+ end
24
+
25
+ def reader_params
26
+ { searchConf: @search_conf }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,20 @@
1
+ require_relative 'base/reader'
2
+
3
+ module Eco::API::UseCases::GraphQL::Helpers::Dashboards
4
+ # Dashboards helper mixin — NATIVE reader over `dashboardSearch`.
5
+ module Base
6
+ include Eco::API::UseCases::GraphQL::Helpers::Base
7
+
8
+ private
9
+
10
+ # Build a lazy reader over the org's dashboards (MinimalDashboardConnection).
11
+ # @param query [String, nil] free-text search shorthand (→ search_conf { query: }).
12
+ # @param search_conf [Hash, nil] full Search input (takes precedence over `query`).
13
+ # @return [Reader]
14
+ def dashboards(query: nil, search_conf: nil)
15
+ conf = search_conf
16
+ conf ||= { query: query } if query
17
+ Reader.new(graphql, search_conf: conf)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ module Eco::API::UseCases::GraphQL::Helpers
2
+ # NATIVE dashboard readers (currentOrganization.dashboardSearch).
3
+ module Dashboards
4
+ end
5
+ end
6
+
7
+ require_relative 'dashboards/base'
@@ -0,0 +1,51 @@
1
+ module Eco::API::UseCases::GraphQL::Helpers::Pages
2
+ # NATIVE reader over `page(id:).activities` (the ActivityInterface behind a page's history /
3
+ # changelog feed). Lazily paginates and yields `Model::Activity` records.
4
+ #
5
+ # Use via `Helpers::Pages::Activities#page_activities`:
6
+ # page_activities(page_id).each { |a| ... }
7
+ # page_activities(page_id, sorters: [{ key: 'updated_at', direction: 'desc' }]).to_a(limit: 50)
8
+ module Activities
9
+ # Lazy activity-feed reader for a single page.
10
+ class Reader
11
+ include Eco::API::UseCases::GraphQL::Helpers::Base::ConnectionReader
12
+
13
+ # @param graphql [Ecoportal::API::GraphQL] the active gem client.
14
+ # @param page_id [String] the page id whose activities to read.
15
+ # @param search_conf [Hash, nil] a `Search` input hash (typically `{ sorters: [...] }`).
16
+ # Defaults to the web feature's ordering: newest updates first.
17
+ def initialize(graphql, page_id, search_conf: nil)
18
+ @graphql = graphql
19
+ @page_id = page_id
20
+ @search_conf = search_conf || DEFAULT_SEARCH_CONF
21
+ end
22
+
23
+ DEFAULT_SEARCH_CONF = { sorters: [{ direction: 'desc', key: 'updated_at' }] }.freeze
24
+
25
+ private
26
+
27
+ def connection_query
28
+ @graphql.currentOrganization.pageActivities
29
+ end
30
+
31
+ def reader_params
32
+ { id: @page_id, searchConf: @search_conf }
33
+ end
34
+ end
35
+
36
+ include Eco::API::UseCases::GraphQL::Helpers::Base
37
+
38
+ private
39
+
40
+ # Build a lazy reader over a page's activity/history feed.
41
+ # @param page_id [String]
42
+ # @param sorters [Array<Hash>, nil] shorthand for `search_conf: { sorters: ... }`.
43
+ # @param search_conf [Hash, nil] full Search input (takes precedence over `sorters`).
44
+ # @return [Reader]
45
+ def page_activities(page_id, sorters: nil, search_conf: nil)
46
+ conf = search_conf
47
+ conf ||= { sorters: sorters } if sorters
48
+ Reader.new(graphql, page_id, search_conf: conf)
49
+ end
50
+ end
51
+ end
@@ -7,12 +7,13 @@ module Eco::API::UseCases::GraphQL::Helpers
7
7
  # with duck-typing so they work against the GraphQL page/section/field models.
8
8
  #
9
9
  # This is Phase 1 of the ooze -> native GraphQL migration (build the shared substrate before
10
- # any case). See the ecoportal-api-graphql repo's internal docs.
10
+ # any case). See ecoportal-api-graphql/.ai-assistance/projects/ooze-graphql-native-migration/.
11
11
  module Pages
12
12
  end
13
13
  end
14
14
 
15
15
  require_relative 'pages/shortcuts'
16
+ require_relative 'pages/activities'
16
17
  require_relative 'pages/filters'
17
18
  require_relative 'pages/ooze_handlers'
18
19
  require_relative 'pages/rescuable'
@@ -7,3 +7,5 @@ require_relative 'helpers/base'
7
7
  require_relative 'helpers/location'
8
8
  require_relative 'helpers/contractors'
9
9
  require_relative 'helpers/pages'
10
+ require_relative 'helpers/access_logs'
11
+ require_relative 'helpers/dashboards'
@@ -0,0 +1,76 @@
1
+ # usecases/graphql/samples
2
+
3
+ Built-in GraphQL sample base classes shipped with the gem.
4
+ These are abstract/semi-abstract classes that org scripts inherit from.
5
+ Concrete, CLI-integrated cases go in `usecases/default/` instead.
6
+
7
+ ---
8
+
9
+ ## Hierarchy convention
10
+
11
+ Each domain follows:
12
+ ```
13
+ samples/<domain>.rb ← namespace loader (may also BE the base class)
14
+ samples/<domain>/
15
+ <level>/
16
+ dsl.rb ← DSL concern — include in base, available to subclasses
17
+ base.rb ← Base class (inherits from GraphQL::Base or parent level)
18
+ <functional_level>.rb ← Optional: opinionated subclass, inherit directly
19
+ <functional_level>/
20
+ dsl.rb ← Further DSL for that functional level
21
+ ```
22
+
23
+ DSLs are always **concerns (modules)** to include — never classes.
24
+ Bases are **classes** with the scaffolding logic.
25
+ Functional levels add opinionated defaults on top of base.
26
+
27
+ ---
28
+
29
+ ## Contents
30
+
31
+ | File | Class | Purpose |
32
+ |------|-------|---------|
33
+ | `samples/location.rb` | `Samples::Location` | Location structure management |
34
+ | `samples/location/command.rb` | `Samples::Location::Command` | Apply location tree commands |
35
+ | `samples/location/service.rb` | `Samples::Location::Service` | Tree diffing and conversion service |
36
+ | `samples/contractors.rb` | `Samples::Contractors` | Contractor entity base case |
37
+ | `samples/contractors/dsl.rb` | `Contractors::DSL` | Contractor helper mixin |
38
+ | `samples/pages.rb` | `Samples::Pages` (namespace) | Page processing cases loader |
39
+ | `samples/pages/page/dsl.rb` | `Pages::Page::DSL` | SearchConf helpers mixin |
40
+ | `samples/pages/page/base.rb` | `Pages::Page::Base` | Register-scoped page iteration |
41
+ | `samples/pages/org_page/dsl.rb` | `Pages::OrgPage::DSL` | Org-page DSL (extends Page::DSL) |
42
+ | `samples/pages/org_page/base.rb` | `Pages::OrgPage::Base` | Org-wide page iteration |
43
+
44
+ ---
45
+
46
+ ## Difference: samples vs org-specific cases vs default
47
+
48
+ | Layer | Location | Purpose |
49
+ |---|---|---|
50
+ | **samples** (here) | `eco-helpers/lib/.../graphql/samples/` | Abstract base classes — org scripts inherit |
51
+ | **default** | `eco-helpers/lib/.../usecases/default/` | Concrete CLI-integrated cases for ALL orgs |
52
+ | **org-specific** | `multi_org_api/{org}/config/graphql_cases/` | Org-specific implementations |
53
+
54
+ Org scripts inherit from `samples/`, optionally via `default/` as an intermediate layer.
55
+
56
+ ---
57
+
58
+ ## Adding a new built-in sample
59
+
60
+ 1. Create the case file in `samples/`:
61
+ ```ruby
62
+ # lib/eco/api/usecases/graphql/samples/my_domain.rb
63
+ class Eco::API::UseCases::GraphQL::Samples::MyDomain < Eco::API::UseCases::GraphQL::Base
64
+ name 'my-domain-case'
65
+ type :other
66
+
67
+ def process
68
+ # ...
69
+ end
70
+ end
71
+ ```
72
+
73
+ 2. Add `require_relative 'samples/my_domain'` to `samples.rb`.
74
+
75
+ If the case is page-centric, inherit from `PageCase` instead of `Base` to get
76
+ pagination, KPI tracking, and `update_page` for free.
@@ -1,5 +1,21 @@
1
1
  module Eco::API::UseCases::GraphQL::Samples
2
2
  module Contractors::DSL
3
3
  include Eco::API::UseCases::GraphQL::Helpers::Contractors::Base
4
+
5
+ private
6
+
7
+ # Sample command: update the org's contractor manager settings (auto-approvals +
8
+ # whether contractor admins may add other admins). Delegates to the guarded helper
9
+ # `#update_contractor_manager_settings` (dry-run/simulate + -no-email honoured).
10
+ #
11
+ # @param auto_approvals [Hash, nil] AutoApprovalsInput ({ enabled:, approvalConditions: }).
12
+ # @param allow_admins_add_admins [Boolean, nil]
13
+ # @return [Hash] the intended input when simulated, else the mutation payload.
14
+ def update_manager_settings(auto_approvals: nil, allow_admins_add_admins: nil)
15
+ update_contractor_manager_settings(
16
+ cm_auto_approvals_settings: auto_approvals,
17
+ allow_contractor_admins_to_add_admins: allow_admins_add_admins
18
+ )
19
+ end
4
20
  end
5
21
  end
@@ -0,0 +1,59 @@
1
+ # samples/pages
2
+
3
+ Base classes for GraphQL-native page processing use cases.
4
+
5
+ ---
6
+
7
+ ## Structure
8
+
9
+ ```
10
+ pages/
11
+ page/
12
+ dsl.rb ← Page::DSL — SearchConf helpers mixin (sc, in_register, state_is, ...)
13
+ base.rb ← Page::Base — register-scoped page iteration + KPI scaffolding
14
+ org_page/
15
+ dsl.rb ← OrgPage::DSL — extends Page::DSL (org-wide helpers)
16
+ base.rb ← OrgPage::Base — org-wide iteration (no default register scope)
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Inheritance
22
+
23
+ ```
24
+ GraphQL::Base
25
+ ↓
26
+ Samples::Pages::Page::Base (register-scoped, inherits Page::DSL)
27
+ ↓
28
+ Samples::Pages::OrgPage::Base (org-wide, overrides search_conf)
29
+ ↓
30
+ your org subclass
31
+ ```
32
+
33
+ ---
34
+
35
+ ## Page::Base — register-scoped scripts
36
+
37
+ Override `process_page(page)` and optionally `search_conf`.
38
+ Set `register_id` and `batch_size` on the class.
39
+
40
+ ## OrgPage::Base — org-wide scripts
41
+
42
+ Same as Page::Base but `search_conf` starts empty.
43
+ Add your own filters via `super.filter(state_is(:active))` etc.
44
+
45
+ ---
46
+
47
+ ## Adding a functional level
48
+
49
+ If a common pattern emerges (e.g., "stage-submit scripts"), add:
50
+
51
+ ```
52
+ pages/page/
53
+ stage_submitter.rb ← Page::StageSubmitter < Page::Base
54
+ stage_submitter/
55
+ dsl.rb ← StageSubmitter::DSL
56
+ ```
57
+
58
+ Keep base.rb for the pure iteration scaffolding; put opinionated defaults in
59
+ the functional level so scripts can choose their entry point.
@@ -1,4 +1,11 @@
1
1
  module Eco::API::UseCases::GraphQL::Samples::Pages
2
+ # NOTE: nested as `module Template` + `class Base` rather than the compact `class Template::Base`
3
+ # ON PURPOSE. The compact form leaves `Template` out of this file's lexical scope, so the bare
4
+ # `CommandEmitter` reference in #desired_commands resolved against Base and Pages only and raised
5
+ # NameError on every call -- the class could never run. Sibling files (command_emitter.rb,
6
+ # csv_build/builder.rb) all open the Template module properly, which is why their bare references
7
+ # to each other work. Keep this nesting.
8
+ #
2
9
  # Build-from-scratch template (workflow) construction use case.
3
10
  #
4
11
  # A subclass declares the desired template structure in #declare(emitter) using the
@@ -17,54 +24,56 @@ module Eco::API::UseCases::GraphQL::Samples::Pages
17
24
  # end
18
25
  # end
19
26
  # end
20
- class Template::Base < Eco::API::UseCases::GraphQL::Base
21
- name 'graphql-template-base'
22
- type :other
27
+ module Template
28
+ class Base < Eco::API::UseCases::GraphQL::Base
29
+ name 'graphql-template-base'
30
+ type :other
23
31
 
24
- require_relative 'command_emitter'
32
+ require_relative 'command_emitter'
25
33
 
26
- def process
27
- commands = desired_commands
28
- if simulate?
29
- log(:info) { preview_message(commands) }
30
- return nil
34
+ def process
35
+ commands = desired_commands
36
+ if simulate?
37
+ log(:info) { preview_message(commands) }
38
+ return nil
39
+ end
40
+ apply(commands)
31
41
  end
32
- apply(commands)
33
- end
34
42
 
35
- # == Subclass override point ================================================
43
+ # == Subclass override point ================================================
36
44
 
37
- # Declare the desired template structure onto the given CommandEmitter.
38
- def declare(_emitter)
39
- raise NotImplementedError, "Implement #declare(emitter) in #{self.class}"
40
- end
45
+ # Declare the desired template structure onto the given CommandEmitter.
46
+ def declare(_emitter)
47
+ raise NotImplementedError, "Implement #declare(emitter) in #{self.class}"
48
+ end
41
49
 
42
- # The ordered command batch this template would apply. Pure — no client needed.
43
- def desired_commands
44
- emitter = CommandEmitter.new
45
- declare(emitter)
46
- emitter.commands
47
- end
50
+ # The ordered command batch this template would apply. Pure — no client needed.
51
+ def desired_commands
52
+ emitter = CommandEmitter.new
53
+ declare(emitter)
54
+ emitter.commands
55
+ end
48
56
 
49
- protected
57
+ protected
50
58
 
51
- # Persist a fresh template from the command batch. Override to #update an existing one.
52
- def apply(commands)
53
- graphql.template.create(commands: commands)
54
- end
59
+ # Persist a fresh template from the command batch. Override to #update an existing one.
60
+ def apply(commands)
61
+ graphql.template.create(commands: commands)
62
+ end
55
63
 
56
- # Update an existing template model with the command batch.
57
- def apply_update(model, commands)
58
- graphql.template.update(model, commands: commands)
59
- end
64
+ # Update an existing template model with the command batch.
65
+ def apply_update(model, commands)
66
+ graphql.template.update(model, commands: commands)
67
+ end
60
68
 
61
- private
69
+ private
62
70
 
63
- def preview_message(commands)
64
- [
65
- "Simulate — would apply #{commands.size} workflow command(s):",
66
- *commands.map { |c| " * #{c.keys.first}: #{c.values.first.inspect}" }
67
- ].join("\n")
71
+ def preview_message(commands)
72
+ [
73
+ "Simulate — would apply #{commands.size} workflow command(s):",
74
+ *commands.map { |c| " * #{c.keys.first}: #{c.values.first.inspect}" }
75
+ ].join("\n")
76
+ end
68
77
  end
69
78
  end
70
79
  end
@@ -1,6 +1,6 @@
1
1
  module Eco::API::UseCases::GraphQL::Samples::Pages
2
2
  # Template (workflow) build-from-scratch + (later) diff-and-update samples.
3
- # See the ecoportal-api-graphql repo's internal docs.
3
+ # See ecoportal-api-graphql/.ai-assistance/projects/template-maintenance/.
4
4
  module Template
5
5
  end
6
6
  end
data/lib/eco/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eco
2
- VERSION = '3.2.23'.freeze
2
+ VERSION = '3.3.0'.freeze
3
3
  end