eco-helpers 3.2.14 → 3.2.16
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/.ai-assistance/conventions/code-working-tree-protocol.md +176 -0
- data/.ai-assistance/scripts/token-logger.js +220 -0
- data/.ai-assistance/scripts/token-report.ts +158 -0
- data/.ai-assistance/scripts/token-session-start.js +66 -0
- data/.ai-assistance/skills/ep-ai-manager/SKILL.md +417 -0
- data/.ai-assistance/skills/ruby-scripting/SKILL.md +215 -0
- data/.ai-assistance/standards-version.json +10 -0
- data/.ai-assistance/token-budget.json +39 -0
- data/.claude/settings.json +103 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +17 -0
- data/CLAUDE.md +83 -0
- data/eco-helpers.gemspec +1 -1
- data/lib/eco/api/usecases/CLAUDE.md +78 -0
- data/lib/eco/api/usecases/default/pages.rb +30 -0
- data/lib/eco/api/usecases/graphql/CLAUDE.md +120 -0
- data/lib/eco/api/usecases/graphql/compat/ooze_redirect/dirty_array.rb +22 -0
- data/lib/eco/api/usecases/graphql/compat/ooze_redirect/field_patches.rb +241 -0
- data/lib/eco/api/usecases/graphql/compat/ooze_redirect/force_compat.rb +73 -0
- data/lib/eco/api/usecases/graphql/compat/ooze_redirect.rb +234 -0
- data/lib/eco/api/usecases/graphql/compat.rb +6 -0
- data/lib/eco/api/usecases/graphql/helpers/CLAUDE.md +79 -0
- data/lib/eco/api/usecases/graphql/samples/CLAUDE.md +76 -0
- data/lib/eco/api/usecases/graphql/samples/pages/CLAUDE.md +59 -0
- data/lib/eco/api/usecases/graphql/samples/pages/org_page/base.rb +41 -0
- data/lib/eco/api/usecases/graphql/samples/pages/org_page/dsl.rb +8 -0
- data/lib/eco/api/usecases/graphql/samples/pages/org_page.rb +7 -0
- data/lib/eco/api/usecases/graphql/samples/pages/page/base.rb +148 -0
- data/lib/eco/api/usecases/graphql/samples/pages/page/dsl.rb +38 -0
- data/lib/eco/api/usecases/graphql/samples/pages/page.rb +7 -0
- data/lib/eco/api/usecases/graphql/samples/pages.rb +7 -0
- data/lib/eco/api/usecases/graphql/samples.rb +1 -0
- data/lib/eco/api/usecases/graphql.rb +1 -0
- data/lib/eco/api/usecases/ooze_samples/ooze_base_case.rb +4 -0
- data/lib/eco/api/usecases/ooze_samples/register_update_case.rb +7 -1
- data/lib/eco/version.rb +1 -1
- metadata +31 -3
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"defaultMode": "auto",
|
|
4
|
+
"allowedTools": [
|
|
5
|
+
"Read"
|
|
6
|
+
],
|
|
7
|
+
"permissionRules": [
|
|
8
|
+
{
|
|
9
|
+
"tool": "Write",
|
|
10
|
+
"pattern": "/**",
|
|
11
|
+
"action": "allow"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"tool": "StrReplace",
|
|
15
|
+
"pattern": "/**",
|
|
16
|
+
"action": "allow"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"allow": [
|
|
20
|
+
"WebFetch(domain:anthropic.com)",
|
|
21
|
+
"WebFetch(domain:npmjs.com)",
|
|
22
|
+
"Write(.glaudeignore)",
|
|
23
|
+
"Update(.glaudeignore)",
|
|
24
|
+
"Bash(rm .ai-assistance/bridge/LOCK)",
|
|
25
|
+
"Read(.git/**)",
|
|
26
|
+
"Read(**/rubygems/**)",
|
|
27
|
+
"Write(*.md)",
|
|
28
|
+
"Edit(.ai-assistance/**)",
|
|
29
|
+
"Update(.ai-assistance/**)",
|
|
30
|
+
"Write(.ai-assistance/**)",
|
|
31
|
+
"Write(lib/**)",
|
|
32
|
+
"Write(spec/**)",
|
|
33
|
+
"Bash(git status)",
|
|
34
|
+
"Bash(git diff *)",
|
|
35
|
+
"Bash(git log *)",
|
|
36
|
+
"Bash(git add *)",
|
|
37
|
+
"Bash(git commit *)",
|
|
38
|
+
"PowerShell(git status)",
|
|
39
|
+
"PowerShell(git diff *)",
|
|
40
|
+
"PowerShell(git log *)",
|
|
41
|
+
"PowerShell(git add *)",
|
|
42
|
+
"PowerShell(git commit *)",
|
|
43
|
+
"Bash(npm test)",
|
|
44
|
+
"Bash(npm run lint)",
|
|
45
|
+
"Bash(npm run build)",
|
|
46
|
+
"Bash(vitest *)",
|
|
47
|
+
"Bash(jest *)",
|
|
48
|
+
"PowerShell(npm test)",
|
|
49
|
+
"PowerShell(npm run lint)",
|
|
50
|
+
"PowerShell(npm run build)",
|
|
51
|
+
"Bash(black .)",
|
|
52
|
+
"Bash(pytest)",
|
|
53
|
+
"Bash(python -m unittest)",
|
|
54
|
+
"Bash(ruff check *)",
|
|
55
|
+
"Bash(bundle exec rspec *)",
|
|
56
|
+
"Bash(bundle exec rubocop *)",
|
|
57
|
+
"PowerShell(pytest)",
|
|
58
|
+
"PowerShell(python -m unittest)",
|
|
59
|
+
"PowerShell(ruff check *)",
|
|
60
|
+
"PowerShell(bundle exec rspec *)",
|
|
61
|
+
"PowerShell(bundle exec rubocop *)",
|
|
62
|
+
"Bash(node .ai-assistance/scripts/token-logger.js)",
|
|
63
|
+
"Bash(node .ai-assistance/scripts/token-session-start.js)"
|
|
64
|
+
],
|
|
65
|
+
"deny": [
|
|
66
|
+
"Read(*.env)",
|
|
67
|
+
"Read(./.env*)",
|
|
68
|
+
"Read(./secrets/**)",
|
|
69
|
+
"Bash(*cat *.env*)",
|
|
70
|
+
"Bash(*grep *.env*)",
|
|
71
|
+
"Bash(printenv*)",
|
|
72
|
+
"Bash(env)",
|
|
73
|
+
"Write(.git/*)",
|
|
74
|
+
"Edit(.git/*)",
|
|
75
|
+
"Bash(git push *)",
|
|
76
|
+
"Bash(rm -rf *)"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"hooks": {
|
|
80
|
+
"SessionStart": [
|
|
81
|
+
{
|
|
82
|
+
"matcher": "",
|
|
83
|
+
"hooks": [
|
|
84
|
+
{
|
|
85
|
+
"type": "command",
|
|
86
|
+
"command": "node .ai-assistance/scripts/token-session-start.js 2>/dev/null || true"
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"Stop": [
|
|
92
|
+
{
|
|
93
|
+
"matcher": "",
|
|
94
|
+
"hooks": [
|
|
95
|
+
{
|
|
96
|
+
"type": "command",
|
|
97
|
+
"command": "node .ai-assistance/scripts/token-logger.js 2>/dev/null || true"
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
}
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [3.2.16] - 2026-07-02
|
|
6
|
+
|
|
7
|
+
APIv2→GraphQL cutover — the OozeRedirect compat layer that runs the maintained ooze integrations
|
|
8
|
+
(toocs-coding, cans-upsert, supplier-documents) on GraphQL. Requires ecoportal-api-graphql >= 1.3.9.
|
|
9
|
+
|
|
10
|
+
### Fixed / Changed
|
|
11
|
+
|
|
12
|
+
- **OozeRedirect slimmed onto the base OozeSamples loop** — removed the `with_each_entry` /
|
|
13
|
+
`update_ooze` / `process_ooze` overrides that duplicated and silently bypassed the base loop
|
|
14
|
+
(KPIs, dedup, queue, `dry_run_feedback`). Fetches go through `ooze → apiv2.pages.get` and saves
|
|
15
|
+
through `update_oozes → update_ooze → apiv2.pages.update`; a captured `submit!`/`sign_off!` rides
|
|
16
|
+
along on the single `updatePage` via `Input::Page::Update.from_model` (reads the `_compat_*` flags).
|
|
17
|
+
- **`dirty?`** also treats a pending `submit!`/`sign_off!` as dirty (so a submit-only page still saves).
|
|
18
|
+
- **`OozeBaseCase#dry_run_feedback`** prints an affirmative `[dry-run] would create/update <ref>` line.
|
|
19
|
+
- **`RegisterUpdateCase#enqueue`** accepts any duck-typed entry (`#dirty?` + `#as_update`), not just
|
|
20
|
+
v2 `Page`/`PageStage` — GraphQL compat pages queue correctly under OozeRedirect.
|
|
21
|
+
|
|
5
22
|
## [3.2.15] - 2026-05-xx
|
|
6
23
|
|
|
7
24
|
### Added
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# CLAUDE.md — eco-helpers
|
|
2
|
+
|
|
3
|
+
AI agent instructions for this repository.
|
|
4
|
+
|
|
5
|
+
**Cross-cutting architecture context lives in `ecoportal-api-graphql` — see its `CLAUDE.md` and `.claude/` folder for the full dependency map, project history, and shared skills.**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Repository Role
|
|
10
|
+
|
|
11
|
+
`eco-helpers` is the **primary downstream consumer** of the EcoPortal API gem stack. It provides a scripting and automation framework for interacting with EcoPortal — CLI tooling, use-case orchestration, data transformation, and batch operations.
|
|
12
|
+
|
|
13
|
+
**Position in chain:**
|
|
14
|
+
```
|
|
15
|
+
ecoportal-api
|
|
16
|
+
ecoportal-api-v2
|
|
17
|
+
ecoportal-api-graphql
|
|
18
|
+
↓
|
|
19
|
+
eco-helpers ← THIS REPO
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Remote:** https://gitlab.ecoportal.co.nz/oscar/script_api_helpers.git
|
|
23
|
+
|
|
24
|
+
**Gem dependencies on the stack:**
|
|
25
|
+
- `ecoportal-api ~> 0.10, >= 0.10.14`
|
|
26
|
+
- `ecoportal-api-v2 ~> 3.3, >= 3.3.1`
|
|
27
|
+
- `ecoportal-api-graphql ~> 1.3, >= 1.3.4`
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Key Folder Layout
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
lib/eco/
|
|
35
|
+
api/ API integration layer
|
|
36
|
+
common/ Shared helpers
|
|
37
|
+
microcases/ Fine-grained reusable operations
|
|
38
|
+
organization/ Org-level resources
|
|
39
|
+
session.rb Session management (entry point for scripting)
|
|
40
|
+
usecases.rb Use-case registry
|
|
41
|
+
policies.rb Access policies
|
|
42
|
+
cli/ CLI framework
|
|
43
|
+
cli_default/ Default CLI options, filters, people workflows
|
|
44
|
+
common/ Cross-cutting utilities
|
|
45
|
+
csv/ CSV reading, streaming, splitting
|
|
46
|
+
data/ Data utilities (fuzzy match, hashes, locations, strings, files)
|
|
47
|
+
language/ Logging, curry, auxiliar utilities
|
|
48
|
+
assets/ Static assets (language files etc.)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Namespace
|
|
54
|
+
|
|
55
|
+
`Eco::` — entirely separate namespace from `Ecoportal::`. Does not reopen upstream gem namespaces.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Key Concerns
|
|
60
|
+
|
|
61
|
+
- This gem is the **backwards-compatibility target** for all upstream gems. When `ecoportal-api-graphql` changes its public interface, check usage here first.
|
|
62
|
+
- `Eco::API::Session` is the main consumer of `Ecoportal::API::GraphQL` — it's the first place to look when checking how GraphQL features are used downstream.
|
|
63
|
+
- The CLI layer (`Eco::CLI`) uses Thor-style commands — changes to API interfaces may silently break CLI workflows if not tested end-to-end.
|
|
64
|
+
- Many operations are batch-oriented with progress logging — error handling and partial-failure behaviour matters.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## How to Find GraphQL Usage
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
grep -r "GraphQL\|graphql\|ecoportal-api-graphql" lib/ --include="*.rb" -l
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This shows which files directly use the GraphQL gem — useful when assessing impact of upstream changes.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Running Tests
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
bundle install
|
|
82
|
+
bundle exec rspec
|
|
83
|
+
```
|
data/eco-helpers.gemspec
CHANGED
|
@@ -42,7 +42,7 @@ Gem::Specification.new do |spec|
|
|
|
42
42
|
spec.add_dependency 'docx', '>= 0.8.0', '< 0.9'
|
|
43
43
|
spec.add_dependency 'dotenv', '~> 3'
|
|
44
44
|
spec.add_dependency 'ecoportal-api', '~> 0.10', '>= 0.10.14'
|
|
45
|
-
spec.add_dependency 'ecoportal-api-graphql', '~> 1.3', '>= 1.3.
|
|
45
|
+
spec.add_dependency 'ecoportal-api-graphql', '~> 1.3', '>= 1.3.9'
|
|
46
46
|
spec.add_dependency 'ecoportal-api-v2', '~> 3.3', '>= 3.3.1'
|
|
47
47
|
spec.add_dependency 'ed25519', '~> 1.2'
|
|
48
48
|
spec.add_dependency 'fast_excel', '>= 0.5.0', '< 0.6'
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# usecases
|
|
2
|
+
|
|
3
|
+
The use-case registry and all built-in case base classes for scripting against EcoPortal.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What a use case is
|
|
8
|
+
|
|
9
|
+
A use case is a self-contained, named, runnable unit of work. It registers itself with
|
|
10
|
+
the CLI framework, receives `session`, `options`, and `usecase` from the runner, and
|
|
11
|
+
executes its `process` (or `process_ooze` / `process_page`) method.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
CLI invokes rake → rake finds registered case → UseCase#launch → main() → process()
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Directory structure
|
|
20
|
+
|
|
21
|
+
| Path | What lives there |
|
|
22
|
+
|------|-----------------|
|
|
23
|
+
| `graphql/` | GraphQL-native base cases + samples (see `graphql/CLAUDE.md`) |
|
|
24
|
+
| `ooze_samples/` | APIv2/REST base cases: `OozeBaseCase`, `RegisterUpdateCase` |
|
|
25
|
+
| `ooze_cases/` | Concrete built-in ooze cases (export register, etc.) |
|
|
26
|
+
| `default/` | Built-in people, location, and utility cases |
|
|
27
|
+
| `default_cases/` | Loader and samples for default cases |
|
|
28
|
+
| `samples/` | Misc driver samples |
|
|
29
|
+
| `graphql.rb` | GraphQL use case loader |
|
|
30
|
+
| `ooze_samples.rb` | Ooze/REST use case loader |
|
|
31
|
+
| `default.rb` | Default use case loader |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Adding a new use case
|
|
36
|
+
|
|
37
|
+
1. Subclass the appropriate base:
|
|
38
|
+
|
|
39
|
+
| Your use case | Inherit from |
|
|
40
|
+
|---|---|
|
|
41
|
+
| Process pages in a register (update workflow) | `Eco::API::UseCases::GraphQL::PageCase` |
|
|
42
|
+
| Process pages org-wide (cross-register, audit) | `Eco::API::UseCases::GraphQL::OrgPageCase` |
|
|
43
|
+
| Custom GraphQL script (export, report, one-off) | `Eco::API::UseCases::GraphQL::Base` |
|
|
44
|
+
| Legacy APIv2 register update | `Eco::API::UseCases::OozeSamples::RegisterUpdateCase` |
|
|
45
|
+
|
|
46
|
+
2. Set `name` and `type`:
|
|
47
|
+
```ruby
|
|
48
|
+
name 'my-case-name' # CLI identifier: called with -my-case-name
|
|
49
|
+
type :other # :people | :contractors | :other
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
3. Override the entry point (`process_page`, `process`, or `process_ooze`).
|
|
53
|
+
|
|
54
|
+
4. Register in the org's `config/cli.rb`:
|
|
55
|
+
```ruby
|
|
56
|
+
cases.add('-my-case-name', :other, 'Description')
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## How cases are launched
|
|
62
|
+
|
|
63
|
+
`Eco::API::UseCases::UseCase#launch` calls `callback.call(*uio.params)` where the
|
|
64
|
+
callback is bound to `method(:main)`. Before launch, `@session` and `@options` are
|
|
65
|
+
injected into the instance — subclasses access them via the `attr_reader` in `CaseEnv`.
|
|
66
|
+
|
|
67
|
+
The `:other` type passes `(session, options, usecase)` positionally to `main`.
|
|
68
|
+
For `GraphQL::Base` subclasses the signature is `main(*_args)` — `session` and
|
|
69
|
+
`options` are already available via the helpers module before `main` is called.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Related
|
|
74
|
+
|
|
75
|
+
- `graphql/CLAUDE.md` — GraphQL case hierarchy, PageCase/OrgPageCase
|
|
76
|
+
- `ooze_samples/` — legacy v2 cases (RegisterUpdateCase, OozeBaseCase)
|
|
77
|
+
- `eco-helpers/CLAUDE.md` — top-level gem context
|
|
78
|
+
- `ecoportal-api-graphql` — upstream gem providing `SearchConf`, `Compat::Pages`, etc.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Eco
|
|
2
|
+
module API
|
|
3
|
+
class UseCases
|
|
4
|
+
class Default
|
|
5
|
+
# Namespace for CLI-integrated page use cases.
|
|
6
|
+
# These are concrete, fully functional cases exposed to all org environments.
|
|
7
|
+
#
|
|
8
|
+
# == Convention
|
|
9
|
+
# Cases here should:
|
|
10
|
+
# - Inherit from Eco::API::UseCases::GraphQL::Samples::Pages::Page::Base
|
|
11
|
+
# (or OrgPage::Base for org-wide operations)
|
|
12
|
+
# - Be registered in the org's config/cli.rb
|
|
13
|
+
# - Be as org-agnostic as possible (accept register_id, filters via options)
|
|
14
|
+
#
|
|
15
|
+
# == Adding a new default page case
|
|
16
|
+
# 1. Create the file here: default/pages/my_case.rb
|
|
17
|
+
# 2. Inherit from the appropriate pages sample base class
|
|
18
|
+
# 3. Require it below
|
|
19
|
+
# 4. Wire CLI registration in usecases/default_cases/samples.rb or the
|
|
20
|
+
# org's config/cli.rb
|
|
21
|
+
#
|
|
22
|
+
# == Currently
|
|
23
|
+
# No default page cases yet — add them here as common patterns emerge
|
|
24
|
+
# across org implementations.
|
|
25
|
+
module Pages
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# usecases/graphql
|
|
2
|
+
|
|
3
|
+
GraphQL-native use case base classes and helpers. All cases here work directly with
|
|
4
|
+
`ecoportal-api-graphql` — no v2 REST layer, no ooze objects.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Class hierarchy
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
Eco::API::Common::Loaders::UseCase (registration + launch)
|
|
12
|
+
↓
|
|
13
|
+
Eco::API::UseCases::GraphQL::Base ← universal GraphQL env
|
|
14
|
+
├── GraphQL::Samples::Pages::Page::Base ← register-scoped pages
|
|
15
|
+
│ ├── GraphQL::Samples::Pages::OrgPage::Base ← org-wide pages
|
|
16
|
+
│ └── your subclass (process_page, search_conf)
|
|
17
|
+
└── your subclass directly (custom scripts: exports, reports, one-offs)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Samples live under `samples/pages/` — NOT in the `graphql/` root. The root only
|
|
21
|
+
has `base.rb`, `helpers.rb`, `utils.rb`, and `samples.rb`.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Base — `graphql/base.rb`
|
|
26
|
+
|
|
27
|
+
Universal GraphQL environment. Provides `graphql`, `session`, `options`, `config`,
|
|
28
|
+
`simulate?`, `log`, `backup` via `Helpers::Base` (see `helpers/CLAUDE.md`).
|
|
29
|
+
|
|
30
|
+
Override `process` to write your script:
|
|
31
|
+
```ruby
|
|
32
|
+
class MyCase < Eco::API::UseCases::GraphQL::Base
|
|
33
|
+
name 'my-case'
|
|
34
|
+
def process
|
|
35
|
+
graphql.currentOrganization.contractorEntities.each { |c| puts c.name }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Pages — `samples/pages/`
|
|
43
|
+
|
|
44
|
+
Page processing base cases. Follow the hierarchy: `page/base` → `org_page/base`.
|
|
45
|
+
|
|
46
|
+
### `samples/pages/page/base.rb` — `Samples::Pages::Page::Base`
|
|
47
|
+
|
|
48
|
+
For **register-scoped** page update workflows.
|
|
49
|
+
|
|
50
|
+
**Class methods:** `register_id 'REG_ID'`, `batch_size 50` (default)
|
|
51
|
+
|
|
52
|
+
**Override points:**
|
|
53
|
+
- `process_page(page)` — **required** — transformation for one page
|
|
54
|
+
- `search_conf` — optional — call `super` to keep register scope, then add filters
|
|
55
|
+
|
|
56
|
+
**Protected helpers:** `update_page`, `skip(reason)`, `each_page`
|
|
57
|
+
|
|
58
|
+
**KPI readers:** `total_pages`, `processed_pages`, `updated_pages`, `skipped_pages`, `failed_pages`
|
|
59
|
+
|
|
60
|
+
**DSL (via `samples/pages/page/dsl.rb`):** `sc`, `in_register`, `state_is`, `external_id_eq`, `updated_since`
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
class Custom::UseCase::UpdateStatus < Eco::API::UseCases::GraphQL::Samples::Pages::Page::Base
|
|
64
|
+
name 'update-status'
|
|
65
|
+
register_id 'REG_ABC'
|
|
66
|
+
|
|
67
|
+
def search_conf
|
|
68
|
+
super.filter(state_is(:active))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def process_page(page)
|
|
72
|
+
page.name = page.name.upcase
|
|
73
|
+
update_page(page)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### `samples/pages/org_page/base.rb` — `Samples::Pages::OrgPage::Base`
|
|
79
|
+
|
|
80
|
+
Inherits `Page::Base`. `search_conf` starts empty (org-wide, no register scope).
|
|
81
|
+
Use for: archive sweeps, cross-register audits, bulk org operations.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Samples — `graphql/samples/`
|
|
86
|
+
|
|
87
|
+
Built-in ready-to-use case implementations:
|
|
88
|
+
- `samples/location.rb` — location structure management cases
|
|
89
|
+
- `samples/contractors.rb` — contractor entity cases
|
|
90
|
+
|
|
91
|
+
See `samples/CLAUDE.md` for details.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Helpers — `graphql/helpers/`
|
|
96
|
+
|
|
97
|
+
Mixins providing domain-specific access patterns. See `helpers/CLAUDE.md`.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Loader order in `graphql.rb`
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
require 'graphql/helpers' # environment mixins (graphql, session, simulate? etc.)
|
|
105
|
+
require 'graphql/utils' # utility modules (SFTP etc.)
|
|
106
|
+
require 'graphql/base' # GraphQL::Base — universal foundation
|
|
107
|
+
require 'graphql/samples' # sample cases: location, contractors, pages, ...
|
|
108
|
+
# └─ graphql/samples/pages.rb
|
|
109
|
+
# └─ pages/page.rb → page/dsl.rb, page/base.rb
|
|
110
|
+
# └─ pages/org_page.rb → org_page/dsl.rb, org_page/base.rb
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Page base cases are in `samples/pages/` — NOT in the `graphql/` root.
|
|
114
|
+
Custom org cases are NOT loaded here — they live in the implementation repo.
|
|
115
|
+
|
|
116
|
+
## default/pages/
|
|
117
|
+
|
|
118
|
+
CLI-integrated page use cases go in `default/pages/` (mirroring `default/locations/`
|
|
119
|
+
and `default/people/`). Currently empty — add cases there when a pattern is common
|
|
120
|
+
enough to expose to all org environments. See `default/pages.rb` for the convention.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Compat::OozeRedirect
|
|
2
|
+
# Array subclass that calls the field's setter when elements are appended,
|
|
3
|
+
# ensuring GraphQL dirty-tracking fires on `fld.people_ids << value`.
|
|
4
|
+
class DirtyArray < Array
|
|
5
|
+
def initialize(field, data)
|
|
6
|
+
@field = field
|
|
7
|
+
super(Array(data))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def <<(value)
|
|
11
|
+
super
|
|
12
|
+
@field.people_ids = to_a
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def push(*values)
|
|
17
|
+
super
|
|
18
|
+
@field.people_ids = to_a
|
|
19
|
+
self
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|