reactor_sdk 0.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +19 -0
- data/LICENSE.txt +21 -0
- data/README.md +281 -0
- data/lib/reactor_sdk/authentication.rb +137 -0
- data/lib/reactor_sdk/client.rb +186 -0
- data/lib/reactor_sdk/configuration.rb +102 -0
- data/lib/reactor_sdk/connection.rb +342 -0
- data/lib/reactor_sdk/endpoints/app_configurations.rb +42 -0
- data/lib/reactor_sdk/endpoints/audit_events.rb +64 -0
- data/lib/reactor_sdk/endpoints/base_endpoint.rb +207 -0
- data/lib/reactor_sdk/endpoints/builds.rb +62 -0
- data/lib/reactor_sdk/endpoints/callbacks.rb +38 -0
- data/lib/reactor_sdk/endpoints/companies.rb +42 -0
- data/lib/reactor_sdk/endpoints/data_elements.rb +251 -0
- data/lib/reactor_sdk/endpoints/environments.rb +174 -0
- data/lib/reactor_sdk/endpoints/extension_package_usage_authorizations.rb +51 -0
- data/lib/reactor_sdk/endpoints/extension_packages.rb +63 -0
- data/lib/reactor_sdk/endpoints/extensions.rb +181 -0
- data/lib/reactor_sdk/endpoints/hosts.rb +101 -0
- data/lib/reactor_sdk/endpoints/libraries.rb +872 -0
- data/lib/reactor_sdk/endpoints/notes.rb +11 -0
- data/lib/reactor_sdk/endpoints/profiles.rb +14 -0
- data/lib/reactor_sdk/endpoints/properties.rb +123 -0
- data/lib/reactor_sdk/endpoints/revisions.rb +102 -0
- data/lib/reactor_sdk/endpoints/rule_components.rb +218 -0
- data/lib/reactor_sdk/endpoints/rules.rb +240 -0
- data/lib/reactor_sdk/endpoints/search.rb +23 -0
- data/lib/reactor_sdk/endpoints/secrets.rb +76 -0
- data/lib/reactor_sdk/error.rb +115 -0
- data/lib/reactor_sdk/library_comparison_builder.rb +74 -0
- data/lib/reactor_sdk/library_snapshot_builder.rb +66 -0
- data/lib/reactor_sdk/paginator.rb +92 -0
- data/lib/reactor_sdk/rate_limiter.rb +96 -0
- data/lib/reactor_sdk/reference_extractor.rb +34 -0
- data/lib/reactor_sdk/resource_metadata.rb +73 -0
- data/lib/reactor_sdk/resource_normalizer.rb +90 -0
- data/lib/reactor_sdk/resources/app_configuration.rb +20 -0
- data/lib/reactor_sdk/resources/audit_event.rb +45 -0
- data/lib/reactor_sdk/resources/base_resource.rb +181 -0
- data/lib/reactor_sdk/resources/build.rb +64 -0
- data/lib/reactor_sdk/resources/callback.rb +16 -0
- data/lib/reactor_sdk/resources/company.rb +38 -0
- data/lib/reactor_sdk/resources/comprehensive_data_element.rb +28 -0
- data/lib/reactor_sdk/resources/comprehensive_extension.rb +30 -0
- data/lib/reactor_sdk/resources/comprehensive_resource.rb +31 -0
- data/lib/reactor_sdk/resources/comprehensive_rule.rb +26 -0
- data/lib/reactor_sdk/resources/comprehensive_upstream_chain.rb +50 -0
- data/lib/reactor_sdk/resources/comprehensive_upstream_chain_entry.rb +34 -0
- data/lib/reactor_sdk/resources/data_element.rb +108 -0
- data/lib/reactor_sdk/resources/environment.rb +45 -0
- data/lib/reactor_sdk/resources/extension.rb +66 -0
- data/lib/reactor_sdk/resources/extension_package.rb +49 -0
- data/lib/reactor_sdk/resources/extension_package_usage_authorization.rb +26 -0
- data/lib/reactor_sdk/resources/host.rb +68 -0
- data/lib/reactor_sdk/resources/library.rb +67 -0
- data/lib/reactor_sdk/resources/library_comparison.rb +72 -0
- data/lib/reactor_sdk/resources/library_comparison_entry.rb +144 -0
- data/lib/reactor_sdk/resources/library_snapshot.rb +118 -0
- data/lib/reactor_sdk/resources/library_snapshot_extension_index.rb +70 -0
- data/lib/reactor_sdk/resources/library_snapshot_index.rb +169 -0
- data/lib/reactor_sdk/resources/library_with_resources.rb +194 -0
- data/lib/reactor_sdk/resources/note.rb +37 -0
- data/lib/reactor_sdk/resources/profile.rb +22 -0
- data/lib/reactor_sdk/resources/property.rb +44 -0
- data/lib/reactor_sdk/resources/revision.rb +156 -0
- data/lib/reactor_sdk/resources/rule.rb +44 -0
- data/lib/reactor_sdk/resources/rule_component.rb +101 -0
- data/lib/reactor_sdk/resources/search_results.rb +28 -0
- data/lib/reactor_sdk/resources/secret.rb +17 -0
- data/lib/reactor_sdk/resources/upstream_chain.rb +80 -0
- data/lib/reactor_sdk/resources/upstream_chain_entry.rb +55 -0
- data/lib/reactor_sdk/response_parser.rb +160 -0
- data/lib/reactor_sdk/version.rb +5 -0
- data/lib/reactor_sdk.rb +79 -0
- data/reactor_sdk.gemspec +70 -0
- data/sig/reactor_sdk.rbs +346 -0
- metadata +293 -0
|
@@ -0,0 +1,872 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
# @file endpoints/libraries.rb
|
|
5
|
+
# @description Endpoint group for Adobe Launch Library resources.
|
|
6
|
+
#
|
|
7
|
+
# Libraries collect rules, data elements, and extensions into a
|
|
8
|
+
# deployable bundle. They move through a state machine:
|
|
9
|
+
# development -> submitted -> approved -> rejected -> published.
|
|
10
|
+
#
|
|
11
|
+
# Resource management methods follow JSON:API relationship semantics:
|
|
12
|
+
#
|
|
13
|
+
# add_* POST /libraries/:id/relationships/:type
|
|
14
|
+
# Adds the specified resources — existing resources are kept.
|
|
15
|
+
# Use for incremental additions.
|
|
16
|
+
#
|
|
17
|
+
# remove_* DELETE /libraries/:id/relationships/:type
|
|
18
|
+
# Removes only the specified resources — others are kept.
|
|
19
|
+
# Use for targeted removals.
|
|
20
|
+
#
|
|
21
|
+
# set_* PATCH /libraries/:id/relationships/:type
|
|
22
|
+
# Replaces the ENTIRE list with exactly what you send.
|
|
23
|
+
# Anything not included is removed. Use with caution —
|
|
24
|
+
# passing an empty array removes all resources of that type.
|
|
25
|
+
#
|
|
26
|
+
# @domain Endpoints
|
|
27
|
+
# @see https://developer.adobe.com/experience-platform/documentation/tags/api/endpoints/libraries/
|
|
28
|
+
#
|
|
29
|
+
|
|
30
|
+
module ReactorSDK
|
|
31
|
+
module Endpoints
|
|
32
|
+
class Libraries < BaseEndpoint
|
|
33
|
+
# Adobe Launch environment stages in upstream order.
|
|
34
|
+
# Development is at the bottom — Production is at the top.
|
|
35
|
+
UPSTREAM_STAGE_ORDER = %w[development staging production].freeze
|
|
36
|
+
|
|
37
|
+
# Maps user-facing library states to the Reactor API transition actions.
|
|
38
|
+
TRANSITION_ACTIONS = {
|
|
39
|
+
'development' => 'develop',
|
|
40
|
+
'develop' => 'develop',
|
|
41
|
+
'submitted' => 'submit',
|
|
42
|
+
'submit' => 'submit',
|
|
43
|
+
'approved' => 'approve',
|
|
44
|
+
'approve' => 'approve',
|
|
45
|
+
'rejected' => 'reject',
|
|
46
|
+
'reject' => 'reject',
|
|
47
|
+
'published' => 'publish',
|
|
48
|
+
'publish' => 'publish'
|
|
49
|
+
}.freeze
|
|
50
|
+
|
|
51
|
+
# ── List and find ───────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
##
|
|
54
|
+
# Lists all libraries for a given property.
|
|
55
|
+
# Follows pagination automatically — returns all libraries.
|
|
56
|
+
#
|
|
57
|
+
# @param property_id [String] Adobe property ID
|
|
58
|
+
# @return [Array<ReactorSDK::Resources::Library>]
|
|
59
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the property does not exist
|
|
60
|
+
#
|
|
61
|
+
def list_for_property(property_id)
|
|
62
|
+
records = @paginator.all("/properties/#{property_id}/libraries")
|
|
63
|
+
records.map { |r| @parser.parse(r, Resources::Library) }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
##
|
|
67
|
+
# Retrieves a single library by its Adobe ID.
|
|
68
|
+
#
|
|
69
|
+
# @param library_id [String] Adobe library ID (format: "LB" + hex string)
|
|
70
|
+
# @return [ReactorSDK::Resources::Library]
|
|
71
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
72
|
+
#
|
|
73
|
+
def find(library_id)
|
|
74
|
+
response = @connection.get("/libraries/#{library_id}")
|
|
75
|
+
@parser.parse(response['data'], Resources::Library)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Fetches a library with all its associated resources included.
|
|
80
|
+
#
|
|
81
|
+
# Calls GET /libraries/:id?include=rules,data_elements,extensions
|
|
82
|
+
# which returns the library alongside all its resources in the
|
|
83
|
+
# JSON:API included array. Each included resource carries its
|
|
84
|
+
# current revision ID in its relationships hash.
|
|
85
|
+
#
|
|
86
|
+
# Returns a LibraryWithResources object exposing:
|
|
87
|
+
# - All standard library attributes
|
|
88
|
+
# - rules, data_elements, extensions arrays with revision_id attached
|
|
89
|
+
# - resource_index for quick revision ID lookup by resource ID
|
|
90
|
+
#
|
|
91
|
+
# @param library_id [String] Adobe library ID
|
|
92
|
+
# @return [ReactorSDK::Resources::LibraryWithResources]
|
|
93
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
94
|
+
#
|
|
95
|
+
def find_with_resources(library_id)
|
|
96
|
+
response = @connection.get(
|
|
97
|
+
"/libraries/#{library_id}",
|
|
98
|
+
params: { 'include' => 'rules,data_elements,extensions' }
|
|
99
|
+
)
|
|
100
|
+
build_library_with_resources(response)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
##
|
|
104
|
+
# Fetches a library snapshot enriched with associated records needed
|
|
105
|
+
# for review workflows.
|
|
106
|
+
#
|
|
107
|
+
# This additive helper builds on find_with_resources and then resolves
|
|
108
|
+
# rule components for every rule present in the library snapshot.
|
|
109
|
+
#
|
|
110
|
+
# The returned object is intentionally built fresh on each call so
|
|
111
|
+
# review workflows never read stale snapshot state after writes.
|
|
112
|
+
#
|
|
113
|
+
# @param library_id [String] Adobe library ID
|
|
114
|
+
# @param property_id [String] Adobe property ID containing the library
|
|
115
|
+
# @return [ReactorSDK::Resources::LibrarySnapshot]
|
|
116
|
+
#
|
|
117
|
+
def find_snapshot(library_id, property_id:)
|
|
118
|
+
snapshot_builder.build(library_id, property_id: property_id)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
##
|
|
122
|
+
# Compares two libraries and returns per-resource review details that
|
|
123
|
+
# can be passed directly into Changeset-style diff tooling.
|
|
124
|
+
#
|
|
125
|
+
# The first library is treated as the current version and the second
|
|
126
|
+
# library is treated as the baseline version. Changeset-style document
|
|
127
|
+
# helpers therefore map baseline content to old_content and current
|
|
128
|
+
# content to new_content.
|
|
129
|
+
#
|
|
130
|
+
# @param current_library_id [String] Library being reviewed
|
|
131
|
+
# @param baseline_library_id [String] Library used as the comparison baseline
|
|
132
|
+
# @param property_id [String] Adobe property ID containing both libraries
|
|
133
|
+
# @return [ReactorSDK::Resources::LibraryComparison]
|
|
134
|
+
#
|
|
135
|
+
def compare(current_library_id, baseline_library_id:, property_id:)
|
|
136
|
+
comparison_builder.build(
|
|
137
|
+
current_library_id,
|
|
138
|
+
baseline_library_id: baseline_library_id,
|
|
139
|
+
property_id: property_id
|
|
140
|
+
)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# ── Create ──────────────────────────────────────────────────
|
|
144
|
+
|
|
145
|
+
##
|
|
146
|
+
# Creates a new library within a property.
|
|
147
|
+
#
|
|
148
|
+
# @param property_id [String] Adobe property ID
|
|
149
|
+
# @param name [String] Display name for the library
|
|
150
|
+
# @return [ReactorSDK::Resources::Library] The newly created library
|
|
151
|
+
# @raise [ReactorSDK::UnprocessableEntityError] if attributes are invalid
|
|
152
|
+
#
|
|
153
|
+
def create(property_id:, name:)
|
|
154
|
+
payload = build_payload('libraries', { name: name })
|
|
155
|
+
response = @connection.post("/properties/#{property_id}/libraries", payload)
|
|
156
|
+
@parser.parse(response['data'], Resources::Library)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
##
|
|
160
|
+
# Updates a library's attributes.
|
|
161
|
+
#
|
|
162
|
+
# @param library_id [String]
|
|
163
|
+
# @param attributes [Hash]
|
|
164
|
+
# @return [ReactorSDK::Resources::Library]
|
|
165
|
+
#
|
|
166
|
+
def update(library_id, attributes)
|
|
167
|
+
update_resource(
|
|
168
|
+
"/libraries/#{library_id}",
|
|
169
|
+
library_id,
|
|
170
|
+
'libraries',
|
|
171
|
+
Resources::Library,
|
|
172
|
+
attributes: attributes
|
|
173
|
+
)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
##
|
|
177
|
+
# Deletes a library.
|
|
178
|
+
#
|
|
179
|
+
# @param library_id [String]
|
|
180
|
+
# @return [nil]
|
|
181
|
+
#
|
|
182
|
+
def delete(library_id)
|
|
183
|
+
delete_resource("/libraries/#{library_id}")
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
##
|
|
187
|
+
# Retrieves the property that owns a library.
|
|
188
|
+
#
|
|
189
|
+
# @param library_id [String]
|
|
190
|
+
# @return [ReactorSDK::Resources::Property]
|
|
191
|
+
#
|
|
192
|
+
def property(library_id)
|
|
193
|
+
fetch_resource("/libraries/#{library_id}/property", Resources::Property)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# ── Rules relationship management ───────────────────────────
|
|
197
|
+
|
|
198
|
+
##
|
|
199
|
+
# Adds rules to a library.
|
|
200
|
+
# Existing rules in the library are preserved — only the specified
|
|
201
|
+
# rules are added.
|
|
202
|
+
#
|
|
203
|
+
# @param library_id [String] Adobe library ID
|
|
204
|
+
# @param rule_ids [Array<String>] Adobe rule IDs to add
|
|
205
|
+
# @return [nil]
|
|
206
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
207
|
+
#
|
|
208
|
+
def add_rules(library_id, rule_ids)
|
|
209
|
+
payload = build_relationship_payload('rules', rule_ids)
|
|
210
|
+
@connection.post("/libraries/#{library_id}/relationships/rules", payload)
|
|
211
|
+
nil
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
##
|
|
215
|
+
# Removes specific rules from a library.
|
|
216
|
+
# Only the specified rules are removed — other rules are preserved.
|
|
217
|
+
#
|
|
218
|
+
# @param library_id [String] Adobe library ID
|
|
219
|
+
# @param rule_ids [Array<String>] Adobe rule IDs to remove
|
|
220
|
+
# @return [nil]
|
|
221
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
222
|
+
#
|
|
223
|
+
def remove_rules(library_id, rule_ids)
|
|
224
|
+
payload = build_relationship_payload('rules', rule_ids)
|
|
225
|
+
@connection.delete_relationship("/libraries/#{library_id}/relationships/rules", payload)
|
|
226
|
+
nil
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
##
|
|
230
|
+
# Replaces the entire rules list for a library.
|
|
231
|
+
# Any rule currently in the library that is NOT in rule_ids is removed.
|
|
232
|
+
# Passing an empty array removes all rules from the library.
|
|
233
|
+
#
|
|
234
|
+
# Use with caution — this is a destructive operation.
|
|
235
|
+
# Prefer add_rules and remove_rules for incremental changes.
|
|
236
|
+
#
|
|
237
|
+
# @param library_id [String] Adobe library ID
|
|
238
|
+
# @param rule_ids [Array<String>] Complete new list of Adobe rule IDs
|
|
239
|
+
# @return [nil]
|
|
240
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
241
|
+
#
|
|
242
|
+
def set_rules(library_id, rule_ids)
|
|
243
|
+
payload = build_relationship_payload('rules', rule_ids)
|
|
244
|
+
@connection.patch("/libraries/#{library_id}/relationships/rules", payload)
|
|
245
|
+
nil
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
##
|
|
249
|
+
# Lists the rules currently assigned to a library.
|
|
250
|
+
#
|
|
251
|
+
# @param library_id [String]
|
|
252
|
+
# @return [Array<ReactorSDK::Resources::Rule>]
|
|
253
|
+
#
|
|
254
|
+
def rules(library_id)
|
|
255
|
+
list_resources("/libraries/#{library_id}/rules", Resources::Rule)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
##
|
|
259
|
+
# Retrieves raw rule relationship linkage for a library.
|
|
260
|
+
#
|
|
261
|
+
# @param library_id [String]
|
|
262
|
+
# @return [Hash, Array<Hash>, nil]
|
|
263
|
+
#
|
|
264
|
+
def rule_relationships(library_id)
|
|
265
|
+
fetch_relationship("/libraries/#{library_id}/relationships/rules")
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# ── Data elements relationship management ───────────────────
|
|
269
|
+
|
|
270
|
+
##
|
|
271
|
+
# Adds data elements to a library.
|
|
272
|
+
# Existing data elements in the library are preserved.
|
|
273
|
+
#
|
|
274
|
+
# @param library_id [String] Adobe library ID
|
|
275
|
+
# @param data_element_ids [Array<String>] Adobe data element IDs to add
|
|
276
|
+
# @return [nil]
|
|
277
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
278
|
+
#
|
|
279
|
+
def add_data_elements(library_id, data_element_ids)
|
|
280
|
+
payload = build_relationship_payload('data_elements', data_element_ids)
|
|
281
|
+
@connection.post("/libraries/#{library_id}/relationships/data_elements", payload)
|
|
282
|
+
nil
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
##
|
|
286
|
+
# Removes specific data elements from a library.
|
|
287
|
+
# Only the specified data elements are removed — others are preserved.
|
|
288
|
+
#
|
|
289
|
+
# @param library_id [String] Adobe library ID
|
|
290
|
+
# @param data_element_ids [Array<String>] Adobe data element IDs to remove
|
|
291
|
+
# @return [nil]
|
|
292
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
293
|
+
#
|
|
294
|
+
def remove_data_elements(library_id, data_element_ids)
|
|
295
|
+
payload = build_relationship_payload('data_elements', data_element_ids)
|
|
296
|
+
@connection.delete_relationship("/libraries/#{library_id}/relationships/data_elements", payload)
|
|
297
|
+
nil
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
##
|
|
301
|
+
# Replaces the entire data elements list for a library.
|
|
302
|
+
# Any data element currently in the library that is NOT in
|
|
303
|
+
# data_element_ids is removed.
|
|
304
|
+
# Passing an empty array removes all data elements from the library.
|
|
305
|
+
#
|
|
306
|
+
# Use with caution — this is a destructive operation.
|
|
307
|
+
#
|
|
308
|
+
# @param library_id [String] Adobe library ID
|
|
309
|
+
# @param data_element_ids [Array<String>] Complete new list of data element IDs
|
|
310
|
+
# @return [nil]
|
|
311
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
312
|
+
#
|
|
313
|
+
def set_data_elements(library_id, data_element_ids)
|
|
314
|
+
payload = build_relationship_payload('data_elements', data_element_ids)
|
|
315
|
+
@connection.patch("/libraries/#{library_id}/relationships/data_elements", payload)
|
|
316
|
+
nil
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
##
|
|
320
|
+
# Lists the data elements currently assigned to a library.
|
|
321
|
+
#
|
|
322
|
+
# @param library_id [String]
|
|
323
|
+
# @return [Array<ReactorSDK::Resources::DataElement>]
|
|
324
|
+
#
|
|
325
|
+
def data_elements(library_id)
|
|
326
|
+
list_resources("/libraries/#{library_id}/data_elements", Resources::DataElement)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
##
|
|
330
|
+
# Retrieves raw data element relationship linkage for a library.
|
|
331
|
+
#
|
|
332
|
+
# @param library_id [String]
|
|
333
|
+
# @return [Hash, Array<Hash>, nil]
|
|
334
|
+
#
|
|
335
|
+
def data_element_relationships(library_id)
|
|
336
|
+
fetch_relationship("/libraries/#{library_id}/relationships/data_elements")
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
# ── Extensions relationship management ──────────────────────
|
|
340
|
+
|
|
341
|
+
##
|
|
342
|
+
# Adds extensions to a library.
|
|
343
|
+
# Existing extensions in the library are preserved.
|
|
344
|
+
#
|
|
345
|
+
# @param library_id [String] Adobe library ID
|
|
346
|
+
# @param extension_ids [Array<String>] Adobe extension IDs to add
|
|
347
|
+
# @return [nil]
|
|
348
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
349
|
+
#
|
|
350
|
+
def add_extensions(library_id, extension_ids)
|
|
351
|
+
payload = build_relationship_payload('extensions', extension_ids)
|
|
352
|
+
@connection.post("/libraries/#{library_id}/relationships/extensions", payload)
|
|
353
|
+
nil
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
##
|
|
357
|
+
# Removes specific extensions from a library.
|
|
358
|
+
# Only the specified extensions are removed — others are preserved.
|
|
359
|
+
#
|
|
360
|
+
# @param library_id [String] Adobe library ID
|
|
361
|
+
# @param extension_ids [Array<String>] Adobe extension IDs to remove
|
|
362
|
+
# @return [nil]
|
|
363
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
364
|
+
#
|
|
365
|
+
def remove_extensions(library_id, extension_ids)
|
|
366
|
+
payload = build_relationship_payload('extensions', extension_ids)
|
|
367
|
+
@connection.delete_relationship("/libraries/#{library_id}/relationships/extensions", payload)
|
|
368
|
+
nil
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
##
|
|
372
|
+
# Replaces the entire extensions list for a library.
|
|
373
|
+
# Any extension currently in the library that is NOT in extension_ids
|
|
374
|
+
# is removed. Passing an empty array removes all extensions.
|
|
375
|
+
#
|
|
376
|
+
# Use with caution — this is a destructive operation.
|
|
377
|
+
#
|
|
378
|
+
# @param library_id [String] Adobe library ID
|
|
379
|
+
# @param extension_ids [Array<String>] Complete new list of extension IDs
|
|
380
|
+
# @return [nil]
|
|
381
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if the library does not exist
|
|
382
|
+
#
|
|
383
|
+
def set_extensions(library_id, extension_ids)
|
|
384
|
+
payload = build_relationship_payload('extensions', extension_ids)
|
|
385
|
+
@connection.patch("/libraries/#{library_id}/relationships/extensions", payload)
|
|
386
|
+
nil
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
##
|
|
390
|
+
# Lists the extensions currently assigned to a library.
|
|
391
|
+
#
|
|
392
|
+
# @param library_id [String]
|
|
393
|
+
# @return [Array<ReactorSDK::Resources::Extension>]
|
|
394
|
+
#
|
|
395
|
+
def extensions(library_id)
|
|
396
|
+
list_resources("/libraries/#{library_id}/extensions", Resources::Extension)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
##
|
|
400
|
+
# Retrieves raw extension relationship linkage for a library.
|
|
401
|
+
#
|
|
402
|
+
# @param library_id [String]
|
|
403
|
+
# @return [Hash, Array<Hash>, nil]
|
|
404
|
+
#
|
|
405
|
+
def extension_relationships(library_id)
|
|
406
|
+
fetch_relationship("/libraries/#{library_id}/relationships/extensions")
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
# ── Environment assignment ──────────────────────────────────
|
|
410
|
+
|
|
411
|
+
##
|
|
412
|
+
# Assigns an environment to a library.
|
|
413
|
+
# A library must have an environment assigned before it can be built.
|
|
414
|
+
#
|
|
415
|
+
# @param library_id [String] Adobe library ID
|
|
416
|
+
# @param environment_id [String] Adobe environment ID to assign
|
|
417
|
+
# @return [nil]
|
|
418
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if either resource does not exist
|
|
419
|
+
#
|
|
420
|
+
def assign_environment(library_id, environment_id)
|
|
421
|
+
payload = { data: { id: environment_id, type: 'environments' } }
|
|
422
|
+
@connection.patch("/libraries/#{library_id}/relationships/environment", payload)
|
|
423
|
+
nil
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
##
|
|
427
|
+
# Retrieves the environment currently assigned to a library.
|
|
428
|
+
#
|
|
429
|
+
# @param library_id [String]
|
|
430
|
+
# @return [ReactorSDK::Resources::Environment]
|
|
431
|
+
#
|
|
432
|
+
def environment(library_id)
|
|
433
|
+
fetch_resource("/libraries/#{library_id}/environment", Resources::Environment)
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
##
|
|
437
|
+
# Retrieves the raw environment relationship for a library.
|
|
438
|
+
#
|
|
439
|
+
# @param library_id [String]
|
|
440
|
+
# @return [Hash, Array<Hash>, nil]
|
|
441
|
+
#
|
|
442
|
+
def environment_relationship(library_id)
|
|
443
|
+
fetch_relationship("/libraries/#{library_id}/relationships/environment")
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
##
|
|
447
|
+
# Removes any assigned environment from a library.
|
|
448
|
+
#
|
|
449
|
+
# @param library_id [String]
|
|
450
|
+
# @return [nil]
|
|
451
|
+
#
|
|
452
|
+
def remove_environment(library_id)
|
|
453
|
+
delete_resource("/libraries/#{library_id}/relationships/environment")
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
# ── State machine ───────────────────────────────────────────
|
|
457
|
+
|
|
458
|
+
##
|
|
459
|
+
# Transitions a library to a new state in its workflow.
|
|
460
|
+
#
|
|
461
|
+
# Valid transitions:
|
|
462
|
+
# development -> submitted -> approved -> published
|
|
463
|
+
# -> rejected -> development
|
|
464
|
+
#
|
|
465
|
+
# @param library_id [String] Adobe library ID
|
|
466
|
+
# @param state [String] Target state to transition to
|
|
467
|
+
# @return [ReactorSDK::Resources::Library] The updated library
|
|
468
|
+
# @raise [ReactorSDK::UnprocessableEntityError] if the transition is invalid
|
|
469
|
+
#
|
|
470
|
+
def transition(library_id, state:)
|
|
471
|
+
payload = {
|
|
472
|
+
data: {
|
|
473
|
+
id: library_id,
|
|
474
|
+
type: 'libraries',
|
|
475
|
+
meta: { action: normalize_transition_action(state) }
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
response = @connection.patch("/libraries/#{library_id}", payload)
|
|
479
|
+
@parser.parse(response['data'], Resources::Library)
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
# ── Build ───────────────────────────────────────────────────
|
|
483
|
+
|
|
484
|
+
##
|
|
485
|
+
# Triggers a build for a library.
|
|
486
|
+
# The library must be in "development" state and have an environment assigned.
|
|
487
|
+
#
|
|
488
|
+
# @param library_id [String] Adobe library ID
|
|
489
|
+
# @return [ReactorSDK::Resources::Build] The triggered build
|
|
490
|
+
# @raise [ReactorSDK::UnprocessableEntityError] if the library cannot be built
|
|
491
|
+
#
|
|
492
|
+
def build(library_id)
|
|
493
|
+
response = @connection.post("/libraries/#{library_id}/builds", {})
|
|
494
|
+
@parser.parse(response['data'], Resources::Build)
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
##
|
|
498
|
+
# Retrieves the immediate upstream library configured for a library.
|
|
499
|
+
#
|
|
500
|
+
# @param library_id [String]
|
|
501
|
+
# @return [ReactorSDK::Resources::Library]
|
|
502
|
+
#
|
|
503
|
+
def upstream_library(library_id)
|
|
504
|
+
fetch_resource("/libraries/#{library_id}/upstream_library", Resources::Library)
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
##
|
|
508
|
+
# Lists notes attached to a library.
|
|
509
|
+
#
|
|
510
|
+
# @param library_id [String]
|
|
511
|
+
# @return [Array<ReactorSDK::Resources::Note>]
|
|
512
|
+
#
|
|
513
|
+
def list_notes(library_id)
|
|
514
|
+
list_notes_for_path("/libraries/#{library_id}/notes")
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
##
|
|
518
|
+
# Creates a note on a library.
|
|
519
|
+
#
|
|
520
|
+
# @param library_id [String]
|
|
521
|
+
# @param text [String]
|
|
522
|
+
# @return [ReactorSDK::Resources::Note]
|
|
523
|
+
#
|
|
524
|
+
def create_note(library_id, text)
|
|
525
|
+
create_note_for_path("/libraries/#{library_id}/notes", text)
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
# ── Upstream resolution ─────────────────────────────────────
|
|
529
|
+
|
|
530
|
+
##
|
|
531
|
+
# Returns the ordered list of libraries upstream of the given library.
|
|
532
|
+
#
|
|
533
|
+
# Adobe Launch uses an environment hierarchy where changes flow upward:
|
|
534
|
+
# Personal Dev → Development → Staging → Production
|
|
535
|
+
#
|
|
536
|
+
# "Upstream" means closer to Production. When a resource does not exist
|
|
537
|
+
# in the target library, the app walks this list in order to find the
|
|
538
|
+
# nearest upstream version to diff against.
|
|
539
|
+
#
|
|
540
|
+
# Examples:
|
|
541
|
+
# Target is Development → returns [staging_library, production_library]
|
|
542
|
+
# Target is Staging → returns [production_library]
|
|
543
|
+
# Target is Production → returns [] (nothing upstream)
|
|
544
|
+
#
|
|
545
|
+
# @param library_id [String] Adobe library ID of the target library
|
|
546
|
+
# @param property_id [String] Adobe property ID
|
|
547
|
+
# @return [Array<ReactorSDK::Resources::Library>] Upstream libraries, nearest first
|
|
548
|
+
# @raise [ReactorSDK::ResourceNotFoundError] if either resource does not exist
|
|
549
|
+
#
|
|
550
|
+
def upstream_libraries(library_id, property_id:)
|
|
551
|
+
find(library_id)
|
|
552
|
+
target_stage = fetch_library_stage(library_id)
|
|
553
|
+
|
|
554
|
+
return [] if target_stage.nil?
|
|
555
|
+
return [] if target_stage == 'production'
|
|
556
|
+
|
|
557
|
+
upstream_stages = stages_above(target_stage)
|
|
558
|
+
all_libraries = list_for_property(property_id)
|
|
559
|
+
|
|
560
|
+
upstream_stages.filter_map do |stage|
|
|
561
|
+
all_libraries.find do |lib|
|
|
562
|
+
fetch_library_stage(lib.id) == stage
|
|
563
|
+
end
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
##
|
|
568
|
+
# Resolves a single resource across the ordered upstream library chain.
|
|
569
|
+
#
|
|
570
|
+
# This is the resource-level convenience wrapper built on top of
|
|
571
|
+
# upstream_libraries and find_with_resources. It allows callers to ask
|
|
572
|
+
# for upstream information directly from a rule, data element, or
|
|
573
|
+
# extension ID without hand-rolling the traversal loop.
|
|
574
|
+
#
|
|
575
|
+
# The returned UpstreamChain object includes:
|
|
576
|
+
# - the target library context
|
|
577
|
+
# - the target resource and target revision_id when present
|
|
578
|
+
# - one UpstreamChainEntry per upstream library, nearest first
|
|
579
|
+
#
|
|
580
|
+
# @param resource_or_id [String, ReactorSDK::Resources::BaseResource]
|
|
581
|
+
# @param library_id [String] Adobe library ID used as the comparison root
|
|
582
|
+
# @param property_id [String] Adobe property ID containing the library chain
|
|
583
|
+
# @param resource_type [String, nil] Optional JSON:API type hint
|
|
584
|
+
# @return [ReactorSDK::Resources::UpstreamChain]
|
|
585
|
+
#
|
|
586
|
+
def upstream_chain_for_resource(resource_or_id, library_id:, property_id:, resource_type: nil)
|
|
587
|
+
resource_id = extract_resource_id(resource_or_id)
|
|
588
|
+
target_library = find_with_resources(library_id)
|
|
589
|
+
target_resource = target_library.all_resources.find { |resource| resource.id == resource_id }
|
|
590
|
+
target_revision_id = target_library.resource_index[resource_id]
|
|
591
|
+
|
|
592
|
+
entries = upstream_libraries(library_id, property_id: property_id).map do |library|
|
|
593
|
+
build_upstream_chain_entry(library, resource_id)
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
Resources::UpstreamChain.new(
|
|
597
|
+
resource_id: resource_id,
|
|
598
|
+
resource_type: resource_type || extract_resource_type(resource_or_id) || target_resource&.type,
|
|
599
|
+
property_id: property_id,
|
|
600
|
+
target_library_id: library_id,
|
|
601
|
+
target_resource: target_resource,
|
|
602
|
+
target_revision_id: target_revision_id,
|
|
603
|
+
entries: entries
|
|
604
|
+
)
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
##
|
|
608
|
+
# Resolves a resource across the ordered upstream library chain using
|
|
609
|
+
# snapshot-aware comprehensive resource wrappers.
|
|
610
|
+
#
|
|
611
|
+
# @param resource_or_id [String, ReactorSDK::Resources::BaseResource]
|
|
612
|
+
# @param library_id [String]
|
|
613
|
+
# @param property_id [String]
|
|
614
|
+
# @param resource_type [String, nil]
|
|
615
|
+
# @return [ReactorSDK::Resources::ComprehensiveUpstreamChain]
|
|
616
|
+
#
|
|
617
|
+
def comprehensive_upstream_chain_for_resource(resource_or_id, library_id:, property_id:, resource_type: nil)
|
|
618
|
+
resource_id = extract_resource_id(resource_or_id)
|
|
619
|
+
snapshot_cache = {}
|
|
620
|
+
target_context = resolve_comprehensive_target_context(
|
|
621
|
+
resource_or_id,
|
|
622
|
+
resource_id,
|
|
623
|
+
library_id,
|
|
624
|
+
property_id,
|
|
625
|
+
snapshot_cache,
|
|
626
|
+
resource_type
|
|
627
|
+
)
|
|
628
|
+
|
|
629
|
+
build_comprehensive_upstream_chain(
|
|
630
|
+
resource_id,
|
|
631
|
+
library_id: library_id,
|
|
632
|
+
property_id: property_id,
|
|
633
|
+
target_context: target_context,
|
|
634
|
+
snapshot_cache: snapshot_cache
|
|
635
|
+
)
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
private
|
|
639
|
+
|
|
640
|
+
##
|
|
641
|
+
# Builds a LibraryWithResources from a full API response that includes
|
|
642
|
+
# rules, data_elements, and extensions in the included array.
|
|
643
|
+
#
|
|
644
|
+
# @param response [Hash] Full JSON:API response from the API
|
|
645
|
+
# @return [ReactorSDK::Resources::LibraryWithResources]
|
|
646
|
+
#
|
|
647
|
+
def build_library_with_resources(response)
|
|
648
|
+
data = response.fetch('data')
|
|
649
|
+
included = Array(response['included'])
|
|
650
|
+
|
|
651
|
+
included_by_type = included.group_by { |r| r['type'] }
|
|
652
|
+
|
|
653
|
+
Resources::LibraryWithResources.new(
|
|
654
|
+
id: data.fetch('id'),
|
|
655
|
+
type: data.fetch('type'),
|
|
656
|
+
attributes: data.fetch('attributes', {}),
|
|
657
|
+
meta: data.fetch('meta', {}),
|
|
658
|
+
included_resources: {
|
|
659
|
+
'rules' => included_by_type.fetch('rules', []),
|
|
660
|
+
'data_elements' => included_by_type.fetch('data_elements', []),
|
|
661
|
+
'extensions' => included_by_type.fetch('extensions', [])
|
|
662
|
+
}
|
|
663
|
+
)
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
##
|
|
667
|
+
# Fetches the environment stage for a library by following its
|
|
668
|
+
# environment relationship.
|
|
669
|
+
#
|
|
670
|
+
# @param library_id [String] Adobe library ID
|
|
671
|
+
# @return [String, nil] Stage ("development", "staging", "production") or nil
|
|
672
|
+
#
|
|
673
|
+
def fetch_library_stage(library_id)
|
|
674
|
+
env_rel = @connection.get("/libraries/#{library_id}/relationships/environment")
|
|
675
|
+
env_id = env_rel&.dig('data', 'id')
|
|
676
|
+
return nil unless env_id
|
|
677
|
+
|
|
678
|
+
env_response = @connection.get("/environments/#{env_id}")
|
|
679
|
+
env_response&.dig('data', 'attributes', 'stage')
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
##
|
|
683
|
+
# Returns the stages upstream of the given stage, nearest first.
|
|
684
|
+
#
|
|
685
|
+
# @param stage [String] Current stage
|
|
686
|
+
# @return [Array<String>] Upstream stages in order
|
|
687
|
+
#
|
|
688
|
+
def stages_above(stage)
|
|
689
|
+
current_index = UPSTREAM_STAGE_ORDER.index(stage)
|
|
690
|
+
return [] if current_index.nil?
|
|
691
|
+
|
|
692
|
+
UPSTREAM_STAGE_ORDER[(current_index + 1)..]
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
##
|
|
696
|
+
# Builds one upstream-chain entry for a specific library and resource ID.
|
|
697
|
+
#
|
|
698
|
+
# @param library [ReactorSDK::Resources::Library]
|
|
699
|
+
# @param resource_id [String]
|
|
700
|
+
# @return [ReactorSDK::Resources::UpstreamChainEntry]
|
|
701
|
+
#
|
|
702
|
+
def build_upstream_chain_entry(library, resource_id)
|
|
703
|
+
library_with_resources = find_with_resources(library.id)
|
|
704
|
+
matched_resource = library_with_resources.all_resources.find { |resource| resource.id == resource_id }
|
|
705
|
+
revision_id = library_with_resources.resource_index[resource_id]
|
|
706
|
+
revision = revision_id ? revisions_endpoint.find(revision_id) : nil
|
|
707
|
+
|
|
708
|
+
Resources::UpstreamChainEntry.new(
|
|
709
|
+
library: library,
|
|
710
|
+
stage: fetch_library_stage(library.id),
|
|
711
|
+
resource: matched_resource,
|
|
712
|
+
revision_id: revision_id,
|
|
713
|
+
revision: revision
|
|
714
|
+
)
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
def build_comprehensive_upstream_chain_entry(library, resource_id, property_id:, resource_type:, snapshot_cache:)
|
|
718
|
+
snapshot = fetch_snapshot(library.id, property_id: property_id, cache: snapshot_cache)
|
|
719
|
+
resource = snapshot.find_resource(resource_id)
|
|
720
|
+
revision_id = snapshot.resource_revision_id(resource_id)
|
|
721
|
+
revision = revision_id ? revisions_endpoint.find(revision_id) : nil
|
|
722
|
+
|
|
723
|
+
Resources::ComprehensiveUpstreamChainEntry.new(
|
|
724
|
+
library: library,
|
|
725
|
+
stage: fetch_library_stage(library.id),
|
|
726
|
+
resource: resource,
|
|
727
|
+
revision_id: revision_id,
|
|
728
|
+
revision: revision,
|
|
729
|
+
comprehensive_resource: snapshot.comprehensive_resource(resource_id, resource_type: resource_type)
|
|
730
|
+
)
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
def resolve_comprehensive_target_context(
|
|
734
|
+
resource_or_id,
|
|
735
|
+
resource_id,
|
|
736
|
+
library_id,
|
|
737
|
+
property_id,
|
|
738
|
+
snapshot_cache,
|
|
739
|
+
resource_type
|
|
740
|
+
)
|
|
741
|
+
snapshot = fetch_snapshot(library_id, property_id: property_id, cache: snapshot_cache)
|
|
742
|
+
build_comprehensive_target_context(resource_or_id, resource_id, snapshot, resource_type)
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
def build_comprehensive_target_context(resource_or_id, resource_id, snapshot, resource_type)
|
|
746
|
+
resource = snapshot.find_resource(resource_id)
|
|
747
|
+
resolved_resource_type = resource_type || extract_resource_type(resource_or_id) || resource&.type
|
|
748
|
+
|
|
749
|
+
{
|
|
750
|
+
resource: resource,
|
|
751
|
+
resource_type: resolved_resource_type,
|
|
752
|
+
revision_id: snapshot.resource_revision_id(resource_id),
|
|
753
|
+
comprehensive_resource: snapshot.comprehensive_resource(resource_id, resource_type: resolved_resource_type)
|
|
754
|
+
}
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
def build_comprehensive_upstream_chain(resource_id, library_id:, property_id:, target_context:, snapshot_cache:)
|
|
758
|
+
Resources::ComprehensiveUpstreamChain.new(
|
|
759
|
+
resource_id: resource_id,
|
|
760
|
+
resource_type: target_context.fetch(:resource_type),
|
|
761
|
+
property_id: property_id,
|
|
762
|
+
target_library_id: library_id,
|
|
763
|
+
target_resource: target_context.fetch(:resource),
|
|
764
|
+
target_revision_id: target_context.fetch(:revision_id),
|
|
765
|
+
target_comprehensive_resource: target_context.fetch(:comprehensive_resource),
|
|
766
|
+
entries: build_comprehensive_upstream_entries(
|
|
767
|
+
library_id,
|
|
768
|
+
property_id,
|
|
769
|
+
resource_id,
|
|
770
|
+
target_context.fetch(:resource_type),
|
|
771
|
+
snapshot_cache
|
|
772
|
+
)
|
|
773
|
+
)
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
def build_comprehensive_upstream_entries(library_id, property_id, resource_id, resource_type, snapshot_cache)
|
|
777
|
+
upstream_libraries(library_id, property_id: property_id).map do |library|
|
|
778
|
+
build_comprehensive_upstream_chain_entry(
|
|
779
|
+
library,
|
|
780
|
+
resource_id,
|
|
781
|
+
property_id: property_id,
|
|
782
|
+
resource_type: resource_type,
|
|
783
|
+
snapshot_cache: snapshot_cache
|
|
784
|
+
)
|
|
785
|
+
end
|
|
786
|
+
end
|
|
787
|
+
|
|
788
|
+
def fetch_snapshot(library_id, property_id:, cache:)
|
|
789
|
+
cache.fetch(snapshot_cache_key(library_id, property_id)) do
|
|
790
|
+
cache[snapshot_cache_key(library_id, property_id)] = find_snapshot(library_id, property_id: property_id)
|
|
791
|
+
end
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
##
|
|
795
|
+
# Normalizes a resource object or raw resource ID into an Adobe ID string.
|
|
796
|
+
#
|
|
797
|
+
# @param resource_or_id [String, #id]
|
|
798
|
+
# @return [String]
|
|
799
|
+
#
|
|
800
|
+
def extract_resource_id(resource_or_id)
|
|
801
|
+
return resource_or_id.id if resource_or_id.respond_to?(:id)
|
|
802
|
+
|
|
803
|
+
resource_or_id
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
##
|
|
807
|
+
# Reads the resource type from a resource object when available.
|
|
808
|
+
#
|
|
809
|
+
# @param resource_or_id [String, #type]
|
|
810
|
+
# @return [String, nil]
|
|
811
|
+
#
|
|
812
|
+
def extract_resource_type(resource_or_id)
|
|
813
|
+
return resource_or_id.type if resource_or_id.respond_to?(:type)
|
|
814
|
+
|
|
815
|
+
nil
|
|
816
|
+
end
|
|
817
|
+
|
|
818
|
+
##
|
|
819
|
+
# Builds a lightweight revisions endpoint sharing this endpoint's deps.
|
|
820
|
+
#
|
|
821
|
+
# @return [ReactorSDK::Endpoints::Revisions]
|
|
822
|
+
#
|
|
823
|
+
def revisions_endpoint
|
|
824
|
+
@revisions_endpoint ||= Endpoints::Revisions.new(
|
|
825
|
+
connection: @connection,
|
|
826
|
+
paginator: @paginator,
|
|
827
|
+
parser: @parser
|
|
828
|
+
)
|
|
829
|
+
end
|
|
830
|
+
|
|
831
|
+
def rule_components_endpoint
|
|
832
|
+
@rule_components_endpoint ||= Endpoints::RuleComponents.new(
|
|
833
|
+
connection: @connection,
|
|
834
|
+
paginator: @paginator,
|
|
835
|
+
parser: @parser
|
|
836
|
+
)
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
def snapshot_builder
|
|
840
|
+
@snapshot_builder ||= ReactorSDK::LibrarySnapshotBuilder.new(
|
|
841
|
+
library_loader: method(:find_with_resources),
|
|
842
|
+
revisions_endpoint: revisions_endpoint,
|
|
843
|
+
rule_components_endpoint: rule_components_endpoint
|
|
844
|
+
)
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
def comparison_builder
|
|
848
|
+
@comparison_builder ||= ReactorSDK::LibraryComparisonBuilder.new(
|
|
849
|
+
snapshot_loader: method(:find_snapshot)
|
|
850
|
+
)
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
def snapshot_cache_key(library_id, property_id)
|
|
854
|
+
"#{property_id}:#{library_id}"
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
##
|
|
858
|
+
# Converts a library state or action alias into the API's expected action.
|
|
859
|
+
#
|
|
860
|
+
# @param state [String, Symbol]
|
|
861
|
+
# @return [String]
|
|
862
|
+
# @raise [ArgumentError] if the transition is unknown
|
|
863
|
+
#
|
|
864
|
+
def normalize_transition_action(state)
|
|
865
|
+
TRANSITION_ACTIONS.fetch(state.to_s) do
|
|
866
|
+
valid = TRANSITION_ACTIONS.keys.uniq.sort.join(', ')
|
|
867
|
+
raise ArgumentError, "Unknown library transition: #{state.inspect}. Expected one of: #{valid}"
|
|
868
|
+
end
|
|
869
|
+
end
|
|
870
|
+
end
|
|
871
|
+
end
|
|
872
|
+
end
|