ecoportal-api-graphql 1.3.9 → 1.3.11
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/code/diff_pairing_engine.md +243 -0
- data/.ai-assistance/code/graphql_domain_knowledge.md +20 -10
- data/.ai-assistance/code/template_diff_pairing_domain.md +175 -0
- data/.ai-assistance/code/workflow-command-guide.md +28 -0
- data/.ai-assistance/projects/TODO.md +21 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/INVENTORY.md +136 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/TODO.md +6 -1
- data/.ai-assistance/projects/qa-services-delivery/DECISIONS.md +93 -0
- data/.ai-assistance/projects/qa-services-delivery/INTENT.md +76 -0
- data/.ai-assistance/projects/qa-services-delivery/PHASE3-SCOPE.md +115 -0
- data/.ai-assistance/projects/qa-services-delivery/ROADMAP.md +99 -0
- data/.ai-assistance/projects/qa-services-delivery/TODO.md +81 -0
- data/.ai-assistance/projects/template-automatic-build-maintenance/INTENT.md +77 -0
- data/.ai-assistance/projects/template-automatic-build-maintenance/TODO.md +97 -0
- data/.ai-assistance/projects/template-diff-deploy/INTENT.md +12 -0
- data/.ai-assistance/projects/template-diff-deploy/TODO.md +9 -0
- data/.ai-assistance/projects/template-maintenance/PHASE0-FINDINGS.md +93 -0
- data/.ai-assistance/projects/template-maintenance/README.md +14 -0
- data/CHANGELOG.md +116 -0
- data/docs/worklog.md +408 -0
- data/ecoportal-api-graphql.gemspec +1 -1
- data/lib/ecoportal/api/graphql/base/page/data_field.rb +1 -1
- data/lib/ecoportal/api/graphql/builder/template_builder.rb +174 -0
- data/lib/ecoportal/api/graphql/builder.rb +17 -16
- data/lib/ecoportal/api/graphql/diff/change.rb +59 -0
- data/lib/ecoportal/api/graphql/diff/command_synthesizer.rb +329 -0
- data/lib/ecoportal/api/graphql/diff/cross_object_diff.rb +165 -0
- data/lib/ecoportal/api/graphql/diff/deploy.rb +121 -0
- data/lib/ecoportal/api/graphql/diff/id_resolver.rb +64 -0
- data/lib/ecoportal/api/graphql/diff/pairing/candidate.rb +32 -0
- data/lib/ecoportal/api/graphql/diff/pairing/engine.rb +173 -0
- data/lib/ecoportal/api/graphql/diff/pairing/ledger.rb +119 -0
- data/lib/ecoportal/api/graphql/diff/pairing/signals.rb +104 -0
- data/lib/ecoportal/api/graphql/diff/strategy.rb +113 -0
- data/lib/ecoportal/api/graphql/diff/version_diff.rb +332 -0
- data/lib/ecoportal/api/graphql/diff.rb +34 -0
- data/lib/ecoportal/api/graphql/fragment/location_draft.rb +53 -53
- data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +1 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_field.rb +27 -18
- data/lib/ecoportal/api/graphql/mutation/action/archive.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/action/create.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/action/update.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/create.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/destroy.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/update.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/kickstand/fail_workflow.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/kickstand/start_workflow.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/kickstand/stop_workflow.rb +1 -1
- data/lib/ecoportal/api/graphql/query/location_structure/draft.rb +62 -62
- data/lib/ecoportal/api/graphql/query/location_structure.rb +61 -61
- data/lib/ecoportal/api/graphql.rb +139 -138
- data/lib/ecoportal/api/graphql_version.rb +1 -1
- data/tests/dump_template_model.rb +90 -0
- data/tests/validate_queries.rb +127 -0
- metadata +32 -3
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
module Ecoportal
|
|
2
|
-
module API
|
|
3
|
-
class GraphQL
|
|
4
|
-
module Query
|
|
5
|
-
class LocationStructure
|
|
6
|
-
class Draft < Logic::Query
|
|
7
|
-
accepted_params :id
|
|
8
|
-
accepted_params :structureId
|
|
9
|
-
accepted_params :includeArchivedNodes, default: true
|
|
10
|
-
|
|
11
|
-
field_name :draft
|
|
12
|
-
|
|
13
|
-
class_resolver :item_class, Model::LocationStructure::Draft
|
|
14
|
-
|
|
15
|
-
private
|
|
16
|
-
|
|
17
|
-
def basic_block(&block)
|
|
18
|
-
final_block = block || default_query_block
|
|
19
|
-
proc {
|
|
20
|
-
query(
|
|
21
|
-
id: :id!,
|
|
22
|
-
structureId: :id!,
|
|
23
|
-
includeArchivedNodes: :boolean
|
|
24
|
-
) {
|
|
25
|
-
currentOrganization {
|
|
26
|
-
locations {
|
|
27
|
-
structure(
|
|
28
|
-
id: :structureId
|
|
29
|
-
) {
|
|
30
|
-
id
|
|
31
|
-
name
|
|
32
|
-
archived
|
|
33
|
-
updatedAt
|
|
34
|
-
draft(
|
|
35
|
-
id: :id,
|
|
36
|
-
&final_block
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def default_query_block
|
|
46
|
-
proc {
|
|
47
|
-
spread :LocationDraft
|
|
48
|
-
structure {
|
|
49
|
-
nodes(
|
|
50
|
-
includeArchived: :includeArchivedNodes
|
|
51
|
-
) {
|
|
52
|
-
spread :LocationNode
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end # Query
|
|
60
|
-
end # GraphQL
|
|
61
|
-
end # API
|
|
62
|
-
end # Ecoportal
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Query
|
|
5
|
+
class LocationStructure
|
|
6
|
+
class Draft < Logic::Query
|
|
7
|
+
accepted_params :id
|
|
8
|
+
accepted_params :structureId
|
|
9
|
+
accepted_params :includeArchivedNodes, default: true
|
|
10
|
+
|
|
11
|
+
field_name :draft
|
|
12
|
+
|
|
13
|
+
class_resolver :item_class, Model::LocationStructure::Draft
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def basic_block(&block)
|
|
18
|
+
final_block = block || default_query_block
|
|
19
|
+
proc {
|
|
20
|
+
query(
|
|
21
|
+
id: :id!,
|
|
22
|
+
structureId: :id!,
|
|
23
|
+
includeArchivedNodes: :boolean
|
|
24
|
+
) {
|
|
25
|
+
currentOrganization {
|
|
26
|
+
locations {
|
|
27
|
+
structure(
|
|
28
|
+
id: :structureId
|
|
29
|
+
) {
|
|
30
|
+
id
|
|
31
|
+
name
|
|
32
|
+
archived
|
|
33
|
+
updatedAt { dateTime timeZone }
|
|
34
|
+
draft(
|
|
35
|
+
id: :id,
|
|
36
|
+
&final_block
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def default_query_block
|
|
46
|
+
proc {
|
|
47
|
+
spread :LocationDraft
|
|
48
|
+
structure {
|
|
49
|
+
nodes(
|
|
50
|
+
includeArchived: :includeArchivedNodes
|
|
51
|
+
) {
|
|
52
|
+
spread :LocationNode
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end # Query
|
|
60
|
+
end # GraphQL
|
|
61
|
+
end # API
|
|
62
|
+
end # Ecoportal
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
module Ecoportal
|
|
2
|
-
module API
|
|
3
|
-
class GraphQL
|
|
4
|
-
module Query
|
|
5
|
-
class LocationStructure < Logic::Query
|
|
6
|
-
accepted_params :id
|
|
7
|
-
accepted_params :includeArchivedNodes, default: true
|
|
8
|
-
|
|
9
|
-
field_name :structure
|
|
10
|
-
|
|
11
|
-
class_resolver :item_class, Model::LocationStructure
|
|
12
|
-
|
|
13
|
-
private
|
|
14
|
-
|
|
15
|
-
def basic_block(&block)
|
|
16
|
-
final_block = block || default_query_block
|
|
17
|
-
proc {
|
|
18
|
-
query(
|
|
19
|
-
id: :id!,
|
|
20
|
-
includeArchivedNodes: :boolean
|
|
21
|
-
) {
|
|
22
|
-
currentOrganization {
|
|
23
|
-
locations {
|
|
24
|
-
structure(id: :id, &final_block)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# At the moment it always retrieves archived nodes!!
|
|
32
|
-
# @note this is on purpose, as via API
|
|
33
|
-
# there isn't much sense in not including archived nodes.
|
|
34
|
-
def default_query_block
|
|
35
|
-
proc {
|
|
36
|
-
id
|
|
37
|
-
name
|
|
38
|
-
archived
|
|
39
|
-
weight
|
|
40
|
-
updatedAt
|
|
41
|
-
visitorManagementEnabled
|
|
42
|
-
nodes(
|
|
43
|
-
includeArchived: :includeArchivedNodes
|
|
44
|
-
) {
|
|
45
|
-
spread :LocationNode
|
|
46
|
-
}
|
|
47
|
-
drafts {
|
|
48
|
-
id
|
|
49
|
-
createdAt
|
|
50
|
-
name
|
|
51
|
-
notes
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
require_relative 'location_structure/draft'
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Query
|
|
5
|
+
class LocationStructure < Logic::Query
|
|
6
|
+
accepted_params :id
|
|
7
|
+
accepted_params :includeArchivedNodes, default: true
|
|
8
|
+
|
|
9
|
+
field_name :structure
|
|
10
|
+
|
|
11
|
+
class_resolver :item_class, Model::LocationStructure
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def basic_block(&block)
|
|
16
|
+
final_block = block || default_query_block
|
|
17
|
+
proc {
|
|
18
|
+
query(
|
|
19
|
+
id: :id!,
|
|
20
|
+
includeArchivedNodes: :boolean
|
|
21
|
+
) {
|
|
22
|
+
currentOrganization {
|
|
23
|
+
locations {
|
|
24
|
+
structure(id: :id, &final_block)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# At the moment it always retrieves archived nodes!!
|
|
32
|
+
# @note this is on purpose, as via API
|
|
33
|
+
# there isn't much sense in not including archived nodes.
|
|
34
|
+
def default_query_block
|
|
35
|
+
proc {
|
|
36
|
+
id
|
|
37
|
+
name
|
|
38
|
+
archived
|
|
39
|
+
weight
|
|
40
|
+
updatedAt { dateTime timeZone }
|
|
41
|
+
visitorManagementEnabled
|
|
42
|
+
nodes(
|
|
43
|
+
includeArchived: :includeArchivedNodes
|
|
44
|
+
) {
|
|
45
|
+
spread :LocationNode
|
|
46
|
+
}
|
|
47
|
+
drafts {
|
|
48
|
+
id
|
|
49
|
+
createdAt
|
|
50
|
+
name
|
|
51
|
+
notes
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
require_relative 'location_structure/draft'
|
|
@@ -1,138 +1,139 @@
|
|
|
1
|
-
module Ecoportal
|
|
2
|
-
module API
|
|
3
|
-
# @attr_reader client [Common::GraphQL::Client] a client object that holds the configuration of the api connection.
|
|
4
|
-
# @attr_reader logger [Logger] the logger.
|
|
5
|
-
class GraphQL
|
|
6
|
-
include Ecoportal::API::Common::GraphQL::ClassHelpers
|
|
7
|
-
|
|
8
|
-
class_resolver :client_class, Ecoportal::API::Common::GraphQL::Client
|
|
9
|
-
|
|
10
|
-
attr_reader :client, :fragments
|
|
11
|
-
|
|
12
|
-
# Creates a `GraphQL` object to interact with the ecoPortal `GraphQL API`.
|
|
13
|
-
# @param org_id [String] the id of the target organization.
|
|
14
|
-
# It defaults to the environmental variable `ORGANIZATION_ID`, if defined
|
|
15
|
-
# @param logger [Logger] an object with `Logger` interface to generate logs.
|
|
16
|
-
def initialize(email: nil, pass: nil, org_id: nil, host: "live.ecoportal.com")
|
|
17
|
-
kargs = {
|
|
18
|
-
email: email,
|
|
19
|
-
pass: pass,
|
|
20
|
-
host: host,
|
|
21
|
-
org_id: org_id,
|
|
22
|
-
no_schema: true
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
@client = client_class.new(**kargs)
|
|
26
|
-
@client.http_client = Ecoportal::API::Common::GraphQL::HttpClient.new(
|
|
27
|
-
email: email,
|
|
28
|
-
pass: pass,
|
|
29
|
-
org_id: org_id,
|
|
30
|
-
host: host
|
|
31
|
-
)
|
|
32
|
-
@fragments = Ecoportal::API::GraphQL::Fragment.new(client)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def currentOrganizationClass
|
|
36
|
-
API::GraphQL::Model::Organization.tap do |org_class|
|
|
37
|
-
org_class.client = client
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def currentOrganization
|
|
42
|
-
currentOrganizationClass
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def createContractorEntity(input:, &block)
|
|
46
|
-
createContractorEntityMutation.query(input: input, &block)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def contractorEntity
|
|
50
|
-
Ecoportal::API::GraphQL::Builder::ContractorEntity.new(client)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Gives a builder to use different options to modify a reporting structure
|
|
54
|
-
def locationStructure
|
|
55
|
-
Ecoportal::API::GraphQL::Builder::LocationStructure.new(client)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Gives a builder to use different options to play with action
|
|
59
|
-
def action
|
|
60
|
-
Ecoportal::API::GraphQL::Builder::Action.new(client)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Gives a builder to use different options to work with pages
|
|
64
|
-
def page
|
|
65
|
-
Ecoportal::API::GraphQL::Builder::Page.new(client)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# v2-compatible pages API — exposes get/get_new/create/update/get_body
|
|
69
|
-
# matching the interface eco-helpers scripts use against ecoportal-api-v2.
|
|
70
|
-
def pages
|
|
71
|
-
Compat::Pages.new(client)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# v2-compatible registers API — exposes search with cursor pagination.
|
|
75
|
-
def registers
|
|
76
|
-
Compat::Registers.new(client)
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Mutation builder for register CRUD + preset view management.
|
|
80
|
-
# Distinct from #registers (compat search layer).
|
|
81
|
-
#
|
|
82
|
-
# Usage:
|
|
83
|
-
# api.register.create(input: { name: 'Safety', moduleType: 'form', filterTags: [] })
|
|
84
|
-
# api.register.preset_view.list('REG_ID')
|
|
85
|
-
# api.register.preset_view.create(input: { registerId: 'R', name: 'Active', fieldConfigs: [] })
|
|
86
|
-
def register
|
|
87
|
-
Ecoportal::API::GraphQL::Builder::Register.new(client)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Kickstand workflow engine controls — start/stop/fail individual workflows
|
|
91
|
-
# or bulk-update a set. Internal back-end automation; not for customer scripts.
|
|
92
|
-
def kickstand
|
|
93
|
-
Builder::Kickstand.new(client)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# Template management — create/update/publish/unpublish templates and manage
|
|
97
|
-
# template information and related pages.
|
|
98
|
-
def template
|
|
99
|
-
Builder::Template.new(client)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# File upload orchestrator — get S3 credentials, upload to S3, register, poll.
|
|
103
|
-
# Returns a fileContainerId string usable in FileField/ImageGallery mutations.
|
|
104
|
-
#
|
|
105
|
-
# Usage:
|
|
106
|
-
# id = api.file_upload.upload('/path/to/report.pdf')
|
|
107
|
-
# page.components.get_by_name('Report').file_container_ids = [id]
|
|
108
|
-
# api.pages.update(page)
|
|
109
|
-
def file_upload
|
|
110
|
-
Ecoportal::API::GraphQL::FileUpload::Client.new(self)
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
private
|
|
114
|
-
|
|
115
|
-
def createContractorEntityMutation
|
|
116
|
-
Ecoportal::API::GraphQL::Mutation::ContractorEntity::Create.new(client)
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
require_relative 'graphql/helpers'
|
|
123
|
-
require_relative 'graphql/concerns'
|
|
124
|
-
require_relative 'graphql/logic/base_model'
|
|
125
|
-
require_relative 'graphql/error'
|
|
126
|
-
require_relative 'graphql/interface'
|
|
127
|
-
require_relative 'graphql/base'
|
|
128
|
-
require_relative 'graphql/model'
|
|
129
|
-
require_relative 'graphql/logic'
|
|
130
|
-
require_relative 'graphql/connection'
|
|
131
|
-
require_relative 'graphql/payload'
|
|
132
|
-
require_relative 'graphql/input'
|
|
133
|
-
require_relative 'graphql/fragment'
|
|
134
|
-
require_relative 'graphql/query'
|
|
135
|
-
require_relative 'graphql/mutation'
|
|
136
|
-
require_relative 'graphql/builder'
|
|
137
|
-
require_relative 'graphql/compat'
|
|
138
|
-
require_relative 'graphql/file_upload'
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
# @attr_reader client [Common::GraphQL::Client] a client object that holds the configuration of the api connection.
|
|
4
|
+
# @attr_reader logger [Logger] the logger.
|
|
5
|
+
class GraphQL
|
|
6
|
+
include Ecoportal::API::Common::GraphQL::ClassHelpers
|
|
7
|
+
|
|
8
|
+
class_resolver :client_class, Ecoportal::API::Common::GraphQL::Client
|
|
9
|
+
|
|
10
|
+
attr_reader :client, :fragments
|
|
11
|
+
|
|
12
|
+
# Creates a `GraphQL` object to interact with the ecoPortal `GraphQL API`.
|
|
13
|
+
# @param org_id [String] the id of the target organization.
|
|
14
|
+
# It defaults to the environmental variable `ORGANIZATION_ID`, if defined
|
|
15
|
+
# @param logger [Logger] an object with `Logger` interface to generate logs.
|
|
16
|
+
def initialize(email: nil, pass: nil, org_id: nil, host: "live.ecoportal.com")
|
|
17
|
+
kargs = {
|
|
18
|
+
email: email,
|
|
19
|
+
pass: pass,
|
|
20
|
+
host: host,
|
|
21
|
+
org_id: org_id,
|
|
22
|
+
no_schema: true
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@client = client_class.new(**kargs)
|
|
26
|
+
@client.http_client = Ecoportal::API::Common::GraphQL::HttpClient.new(
|
|
27
|
+
email: email,
|
|
28
|
+
pass: pass,
|
|
29
|
+
org_id: org_id,
|
|
30
|
+
host: host
|
|
31
|
+
)
|
|
32
|
+
@fragments = Ecoportal::API::GraphQL::Fragment.new(client)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def currentOrganizationClass
|
|
36
|
+
API::GraphQL::Model::Organization.tap do |org_class|
|
|
37
|
+
org_class.client = client
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def currentOrganization
|
|
42
|
+
currentOrganizationClass
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def createContractorEntity(input:, &block)
|
|
46
|
+
createContractorEntityMutation.query(input: input, &block)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def contractorEntity
|
|
50
|
+
Ecoportal::API::GraphQL::Builder::ContractorEntity.new(client)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Gives a builder to use different options to modify a reporting structure
|
|
54
|
+
def locationStructure
|
|
55
|
+
Ecoportal::API::GraphQL::Builder::LocationStructure.new(client)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Gives a builder to use different options to play with action
|
|
59
|
+
def action
|
|
60
|
+
Ecoportal::API::GraphQL::Builder::Action.new(client)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Gives a builder to use different options to work with pages
|
|
64
|
+
def page
|
|
65
|
+
Ecoportal::API::GraphQL::Builder::Page.new(client)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# v2-compatible pages API — exposes get/get_new/create/update/get_body
|
|
69
|
+
# matching the interface eco-helpers scripts use against ecoportal-api-v2.
|
|
70
|
+
def pages
|
|
71
|
+
Compat::Pages.new(client)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# v2-compatible registers API — exposes search with cursor pagination.
|
|
75
|
+
def registers
|
|
76
|
+
Compat::Registers.new(client)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Mutation builder for register CRUD + preset view management.
|
|
80
|
+
# Distinct from #registers (compat search layer).
|
|
81
|
+
#
|
|
82
|
+
# Usage:
|
|
83
|
+
# api.register.create(input: { name: 'Safety', moduleType: 'form', filterTags: [] })
|
|
84
|
+
# api.register.preset_view.list('REG_ID')
|
|
85
|
+
# api.register.preset_view.create(input: { registerId: 'R', name: 'Active', fieldConfigs: [] })
|
|
86
|
+
def register
|
|
87
|
+
Ecoportal::API::GraphQL::Builder::Register.new(client)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Kickstand workflow engine controls — start/stop/fail individual workflows
|
|
91
|
+
# or bulk-update a set. Internal back-end automation; not for customer scripts.
|
|
92
|
+
def kickstand
|
|
93
|
+
Builder::Kickstand.new(client)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Template management — create/update/publish/unpublish templates and manage
|
|
97
|
+
# template information and related pages.
|
|
98
|
+
def template
|
|
99
|
+
Builder::Template.new(client)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# File upload orchestrator — get S3 credentials, upload to S3, register, poll.
|
|
103
|
+
# Returns a fileContainerId string usable in FileField/ImageGallery mutations.
|
|
104
|
+
#
|
|
105
|
+
# Usage:
|
|
106
|
+
# id = api.file_upload.upload('/path/to/report.pdf')
|
|
107
|
+
# page.components.get_by_name('Report').file_container_ids = [id]
|
|
108
|
+
# api.pages.update(page)
|
|
109
|
+
def file_upload
|
|
110
|
+
Ecoportal::API::GraphQL::FileUpload::Client.new(self)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
def createContractorEntityMutation
|
|
116
|
+
Ecoportal::API::GraphQL::Mutation::ContractorEntity::Create.new(client)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
require_relative 'graphql/helpers'
|
|
123
|
+
require_relative 'graphql/concerns'
|
|
124
|
+
require_relative 'graphql/logic/base_model'
|
|
125
|
+
require_relative 'graphql/error'
|
|
126
|
+
require_relative 'graphql/interface'
|
|
127
|
+
require_relative 'graphql/base'
|
|
128
|
+
require_relative 'graphql/model'
|
|
129
|
+
require_relative 'graphql/logic'
|
|
130
|
+
require_relative 'graphql/connection'
|
|
131
|
+
require_relative 'graphql/payload'
|
|
132
|
+
require_relative 'graphql/input'
|
|
133
|
+
require_relative 'graphql/fragment'
|
|
134
|
+
require_relative 'graphql/query'
|
|
135
|
+
require_relative 'graphql/mutation'
|
|
136
|
+
require_relative 'graphql/builder'
|
|
137
|
+
require_relative 'graphql/compat'
|
|
138
|
+
require_relative 'graphql/file_upload'
|
|
139
|
+
require_relative 'graphql/diff'
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require_relative 'local_libs'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
5
|
+
# Dump a TEMPLATE's GraphQL model to JSON, so a real template can be captured as the golden
|
|
6
|
+
# fixture for the template-editing pipeline (build-from-scratch + diff-and-update).
|
|
7
|
+
#
|
|
8
|
+
# A template IS a page in this API (Query::Templates returns PageUnion nodes), so its structural
|
|
9
|
+
# skeleton — stages -> sections -> components(fields) — comes from the ordinary page model, exactly
|
|
10
|
+
# like tests/dump_page_model.rb. On top of that, this tool also captures the page's *workflow
|
|
11
|
+
# command log* (Query::PagesWorkflowCommands) — the applied command history that drives the
|
|
12
|
+
# workflow builder (callbacks / operations / strategies / recipients config).
|
|
13
|
+
#
|
|
14
|
+
# Two artefacts are written per template:
|
|
15
|
+
# spec/fixtures/templates/<id>[_<label>].json -> structural page doc (golden master)
|
|
16
|
+
# spec/fixtures/templates/<id>[_<label>].commands.json -> workflow command log (if readable)
|
|
17
|
+
#
|
|
18
|
+
# Usage (run where the GraphQL connection is configured, like the other tests/):
|
|
19
|
+
# ruby tests/dump_template_model.rb <TEMPLATE_ID> [--out PATH] [--label before|after]
|
|
20
|
+
#
|
|
21
|
+
# Reference target (see .ai-assistance/projects/template-maintenance/DESIGN.md):
|
|
22
|
+
# ruby tests/dump_template_model.rb 6a3fa5b8f89e07c758df622b --label golden
|
|
23
|
+
#
|
|
24
|
+
# Run --label before / --label after around an executeWorkflowCommands batch to diff exactly
|
|
25
|
+
# what a command sequence changed — the same before/after workflow dump_page_model.rb enables.
|
|
26
|
+
|
|
27
|
+
def parse_args(argv)
|
|
28
|
+
opts = { template_id: nil, out: nil, label: nil }
|
|
29
|
+
rest = argv.dup
|
|
30
|
+
opts[:template_id] = rest.shift
|
|
31
|
+
until rest.empty?
|
|
32
|
+
flag = rest.shift
|
|
33
|
+
case flag
|
|
34
|
+
when '--out' then opts[:out] = rest.shift
|
|
35
|
+
when '--label' then opts[:label] = rest.shift
|
|
36
|
+
else
|
|
37
|
+
warn "Unknown argument: #{flag}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
opts
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
opts = parse_args(ARGV)
|
|
44
|
+
|
|
45
|
+
unless opts[:template_id]
|
|
46
|
+
warn 'Usage: ruby tests/dump_template_model.rb <TEMPLATE_ID> [--out PATH] [--label before|after]'
|
|
47
|
+
exit 1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
default_dir = File.expand_path('../spec/fixtures/templates', __dir__)
|
|
51
|
+
default_name = [opts[:template_id], opts[:label]].compact.join('_')
|
|
52
|
+
struct_path = opts[:out] || File.join(default_dir, "#{default_name}.json")
|
|
53
|
+
commands_path = File.join(File.dirname(struct_path), "#{File.basename(struct_path, '.json')}.commands.json")
|
|
54
|
+
|
|
55
|
+
api = Ecoportal::API::GraphQL.new
|
|
56
|
+
|
|
57
|
+
# 1) Structural skeleton — a template is a page, so fetch it via the page model.
|
|
58
|
+
page = api.pages.get(opts[:template_id])
|
|
59
|
+
|
|
60
|
+
if page.nil?
|
|
61
|
+
warn "Could not fetch template '#{opts[:template_id]}' as a page"
|
|
62
|
+
exit 2
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
doc = page.respond_to?(:doc) ? page.doc : page.instance_variable_get(:@page)&.doc
|
|
66
|
+
|
|
67
|
+
FileUtils.mkdir_p(File.dirname(struct_path))
|
|
68
|
+
File.write(struct_path, JSON.pretty_generate(doc))
|
|
69
|
+
|
|
70
|
+
puts "Dumped template structure '#{opts[:template_id]}' -> #{struct_path}"
|
|
71
|
+
puts " name: #{page.respond_to?(:name) ? page.name : '(n/a)'}"
|
|
72
|
+
puts " patchVer: #{page.respond_to?(:patchVer) ? page.patchVer : '(n/a)'}"
|
|
73
|
+
|
|
74
|
+
# 2) Workflow command log — the applied-command history behind the workflow builder.
|
|
75
|
+
# Wrapped in a rescue: the PagesWorkflow read model is still partial (stages is a bare
|
|
76
|
+
# passarray as of SCHEMA_VERSION 20260605), so treat this as best-effort.
|
|
77
|
+
begin
|
|
78
|
+
query = Ecoportal::API::GraphQL::Query::PagesWorkflowCommands.new(api.client)
|
|
79
|
+
commands = []
|
|
80
|
+
query.each(id: opts[:template_id], first: 100) do |cmd|
|
|
81
|
+
commands << (cmd.respond_to?(:doc) ? cmd.doc : cmd)
|
|
82
|
+
end
|
|
83
|
+
File.write(commands_path, JSON.pretty_generate(commands))
|
|
84
|
+
puts "Dumped #{commands.size} workflow command(s) -> #{commands_path}"
|
|
85
|
+
rescue StandardError => e
|
|
86
|
+
warn "Workflow command log not captured (#{e.class}: #{e.message})"
|
|
87
|
+
warn ' -> structural fixture is still valid; the command log read may be WIP for this org.'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
puts 'Tip: capture --label before and --label after an executeWorkflowCommands batch, then diff the JSON.'
|