Class: ReactorSDK::Endpoints::Libraries

Inherits:
BaseEndpoint show all
Defined in:
lib/reactor_sdk/endpoints/libraries.rb

Constant Summary collapse

UPSTREAM_STAGE_ORDER =

Adobe Launch environment stages in upstream order. Development is at the bottom — Production is at the top.

%w[development staging production].freeze
TRANSITION_ACTIONS =

Maps user-facing library states to the Reactor API transition actions.

{
  'development' => 'develop',
  'develop' => 'develop',
  'submitted' => 'submit',
  'submit' => 'submit',
  'approved' => 'approve',
  'approve' => 'approve',
  'rejected' => 'reject',
  'reject' => 'reject',
  'published' => 'publish',
  'publish' => 'publish'
}.freeze

Instance Method Summary collapse

Methods inherited from BaseEndpoint

#initialize

Constructor Details

This class inherits a constructor from ReactorSDK::Endpoints::BaseEndpoint

Instance Method Details

#add_data_elements(library_id, data_element_ids) ⇒ nil

Adds data elements to a library. Existing data elements in the library are preserved.

Parameters:

  • library_id (String)

    Adobe library ID

  • data_element_ids (Array<String>)

    Adobe data element IDs to add

Returns:

  • (nil)

Raises:



309
310
311
312
313
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 309

def add_data_elements(library_id, data_element_ids)
  payload = build_relationship_payload('data_elements', data_element_ids)
  @connection.post("/libraries/#{library_id}/relationships/data_elements", payload)
  nil
end

#add_extensions(library_id, extension_ids) ⇒ nil

Adds extensions to a library. Existing extensions in the library are preserved.

Parameters:

  • library_id (String)

    Adobe library ID

  • extension_ids (Array<String>)

    Adobe extension IDs to add

Returns:

  • (nil)

Raises:



380
381
382
383
384
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 380

def add_extensions(library_id, extension_ids)
  payload = build_relationship_payload('extensions', extension_ids)
  @connection.post("/libraries/#{library_id}/relationships/extensions", payload)
  nil
end

#add_rules(library_id, rule_ids) ⇒ nil

Adds rules to a library. Existing rules in the library are preserved — only the specified rules are added.

Parameters:

  • library_id (String)

    Adobe library ID

  • rule_ids (Array<String>)

    Adobe rule IDs to add

Returns:

  • (nil)

Raises:



238
239
240
241
242
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 238

def add_rules(library_id, rule_ids)
  payload = build_relationship_payload('rules', rule_ids)
  @connection.post("/libraries/#{library_id}/relationships/rules", payload)
  nil
end

#assign_environment(library_id, environment_id) ⇒ nil

Assigns an environment to a library. A library must have an environment assigned before it can be built.

Parameters:

  • library_id (String)

    Adobe library ID

  • environment_id (String)

    Adobe environment ID to assign

Returns:

  • (nil)

Raises:



450
451
452
453
454
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 450

def assign_environment(library_id, environment_id)
  payload = { data: { id: environment_id, type: 'environments' } }
  @connection.patch("/libraries/#{library_id}/relationships/environment", payload)
  nil
end

#build(library_id) ⇒ ReactorSDK::Resources::Build

Triggers a build for a library. The library must be in “development” state and have an environment assigned.

Parameters:

  • library_id (String)

    Adobe library ID

Returns:

Raises:



522
523
524
525
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 522

def build(library_id)
  response = @connection.post("/libraries/#{library_id}/builds", {})
  @parser.parse(response['data'], Resources::Build)
end

#compare(current_library_id, baseline_library_id:, property_id:) ⇒ ReactorSDK::Resources::LibraryComparison

Compares two libraries and returns per-resource review details that can be passed directly into Changeset-style diff tooling.

The first library is treated as the current version and the second library is treated as the baseline version. Changeset-style document helpers therefore map baseline content to old_content and current content to new_content.

Parameters:

  • current_library_id (String)

    Library being reviewed

  • baseline_library_id (String)

    Library used as the comparison baseline

  • property_id (String)

    Adobe property ID containing both libraries

Returns:



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 156

def compare(current_library_id, baseline_library_id:, property_id:)
  snapshot_cache = {}

  comparison_builder.build(
    current_library_id,
    baseline_library_id: baseline_library_id,
    property_id: property_id,
    current_snapshot: fetch_effective_snapshot(current_library_id, property_id: property_id,
                                                                   cache: snapshot_cache),
    baseline_snapshot: fetch_effective_snapshot(
      baseline_library_id,
      property_id: property_id,
      cache: snapshot_cache
    )
  )
end

#comprehensive_upstream_chain_for_resource(resource_or_id, library_id:, property_id:, resource_type: nil) ⇒ ReactorSDK::Resources::ComprehensiveUpstreamChain

Resolves a resource across the ordered upstream library chain using snapshot-aware comprehensive resource wrappers.

Parameters:

Returns:



647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 647

def comprehensive_upstream_chain_for_resource(resource_or_id, library_id:, property_id:, resource_type: nil)
  resource_id = extract_resource_id(resource_or_id)
  snapshot_cache = {}
  target_context = resolve_comprehensive_target_context(
    resource_or_id,
    resource_id,
    library_id,
    property_id,
    snapshot_cache,
    resource_type
  )

  build_comprehensive_upstream_chain(
    resource_id,
    library_id: library_id,
    property_id: property_id,
    target_context: target_context,
    snapshot_cache: snapshot_cache
  )
end

#create(property_id:, name:) ⇒ ReactorSDK::Resources::Library

Creates a new library within a property.

Parameters:

  • property_id (String)

    Adobe property ID

  • name (String)

    Display name for the library

Returns:

Raises:



183
184
185
186
187
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 183

def create(property_id:, name:)
  payload  = build_payload('libraries', { name: name })
  response = @connection.post("/properties/#{property_id}/libraries", payload)
  @parser.parse(response['data'], Resources::Library)
end

#create_note(library_id, text) ⇒ ReactorSDK::Resources::Note

Creates a note on a library.

Parameters:

  • library_id (String)
  • text (String)

Returns:



554
555
556
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 554

def create_note(library_id, text)
  create_note_for_path("/libraries/#{library_id}/notes", text)
end

#data_element_relationships(library_id) ⇒ Hash, ...

Retrieves raw data element relationship linkage for a library.

Parameters:

  • library_id (String)

Returns:

  • (Hash, Array<Hash>, nil)


365
366
367
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 365

def data_element_relationships(library_id)
  fetch_relationship("/libraries/#{library_id}/relationships/data_elements")
end

#data_elements(library_id) ⇒ Array<ReactorSDK::Resources::DataElement>

Lists the data elements currently assigned to a library.

Parameters:

  • library_id (String)

Returns:



355
356
357
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 355

def data_elements(library_id)
  list_resources("/libraries/#{library_id}/data_elements", Resources::DataElement)
end

#delete(library_id) ⇒ nil

Deletes a library.

Parameters:

  • library_id (String)

Returns:

  • (nil)


212
213
214
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 212

def delete(library_id)
  delete_resource("/libraries/#{library_id}")
end

#environment(library_id) ⇒ ReactorSDK::Resources::Environment

Retrieves the environment currently assigned to a library.

Parameters:

  • library_id (String)

Returns:



462
463
464
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 462

def environment(library_id)
  fetch_resource("/libraries/#{library_id}/environment", Resources::Environment)
end

#environment_relationship(library_id) ⇒ Hash, ...

Retrieves the raw environment relationship for a library.

Parameters:

  • library_id (String)

Returns:

  • (Hash, Array<Hash>, nil)


472
473
474
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 472

def environment_relationship(library_id)
  fetch_relationship("/libraries/#{library_id}/relationships/environment")
end

#extension_relationships(library_id) ⇒ Hash, ...

Retrieves raw extension relationship linkage for a library.

Parameters:

  • library_id (String)

Returns:

  • (Hash, Array<Hash>, nil)


435
436
437
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 435

def extension_relationships(library_id)
  fetch_relationship("/libraries/#{library_id}/relationships/extensions")
end

#extensions(library_id) ⇒ Array<ReactorSDK::Resources::Extension>

Lists the extensions currently assigned to a library.

Parameters:

  • library_id (String)

Returns:



425
426
427
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 425

def extensions(library_id)
  list_resources("/libraries/#{library_id}/extensions", Resources::Extension)
end

#find(library_id) ⇒ ReactorSDK::Resources::Library

Retrieves a single library by its Adobe ID.

Parameters:

  • library_id (String)

    Adobe library ID (format: “LB” + hex string)

Returns:

Raises:



73
74
75
76
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 73

def find(library_id)
  response = @connection.get("/libraries/#{library_id}")
  @parser.parse(response['data'], Resources::Library)
end

#find_direct_snapshot(library_id, property_id:) ⇒ ReactorSDK::Resources::LibrarySnapshot

Fetches the direct snapshot for a library without inheriting any upstream resources.

This preserves the pre-1.0 direct-only snapshot behavior for callers that need to inspect exactly what is attached to one library.

Parameters:

  • library_id (String)

    Adobe library ID

  • property_id (String)

    Adobe property ID containing the library

Returns:



138
139
140
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 138

def find_direct_snapshot(library_id, property_id:)
  direct_snapshot_builder.build(library_id, property_id: property_id)
end

#find_snapshot(library_id, property_id:) ⇒ ReactorSDK::Resources::LibrarySnapshot

Fetches the effective library snapshot used by Launch review flows.

Effective snapshots include both:

- resources directly attached to the target library
- inherited upstream resources when the target library does not
  override them

Rule components are resolved against the effective rule revision so inherited rules carry the point-in-time component set a reviewer would see in Adobe Launch.

The returned object is intentionally built fresh on each call so review workflows never read stale snapshot state after writes.

Parameters:

  • library_id (String)

    Adobe library ID

  • property_id (String)

    Adobe property ID containing the library

Returns:



123
124
125
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 123

def find_snapshot(library_id, property_id:)
  fetch_effective_snapshot(library_id, property_id: property_id, cache: {})
end

#find_with_resources(library_id) ⇒ ReactorSDK::Resources::LibraryWithResources

Fetches a library with all its associated resources included.

Calls GET /libraries/:id?include=rules,data_elements,extensions. When Adobe returns the JSON:API included payload, the SDK uses it directly. When Adobe omits included, the SDK falls back to the related /rules, /data_elements, and /extensions endpoints so the result still reflects the library’s directly attached resources.

Returns a LibraryWithResources object exposing:

- All standard library attributes
- rules, data_elements, extensions arrays with revision_id attached
- resource_index for quick revision ID lookup by resource ID

Parameters:

  • library_id (String)

    Adobe library ID

Returns:

Raises:



96
97
98
99
100
101
102
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 96

def find_with_resources(library_id)
  response = @connection.get(
    "/libraries/#{library_id}",
    params: { 'include' => 'rules,data_elements,extensions' }
  )
  build_library_with_resources(response, library_id: library_id)
end

#list_for_property(property_id) ⇒ Array<ReactorSDK::Resources::Library>

Lists all libraries for a given property. Follows pagination automatically — returns all libraries.

Parameters:

  • property_id (String)

    Adobe property ID

Returns:

Raises:



61
62
63
64
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 61

def list_for_property(property_id)
  records = @paginator.all("/properties/#{property_id}/libraries")
  records.map { |r| @parser.parse(r, Resources::Library) }
end

#list_notes(library_id) ⇒ Array<ReactorSDK::Resources::Note>

Lists notes attached to a library.

Parameters:

  • library_id (String)

Returns:



543
544
545
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 543

def list_notes(library_id)
  list_notes_for_path("/libraries/#{library_id}/notes")
end

#property(library_id) ⇒ ReactorSDK::Resources::Property

Retrieves the property that owns a library.

Parameters:

  • library_id (String)

Returns:



222
223
224
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 222

def property(library_id)
  fetch_resource("/libraries/#{library_id}/property", Resources::Property)
end

#remove_data_elements(library_id, data_element_ids) ⇒ nil

Removes specific data elements from a library. Only the specified data elements are removed — others are preserved.

Parameters:

  • library_id (String)

    Adobe library ID

  • data_element_ids (Array<String>)

    Adobe data element IDs to remove

Returns:

  • (nil)

Raises:



324
325
326
327
328
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 324

def remove_data_elements(library_id, data_element_ids)
  payload = build_relationship_payload('data_elements', data_element_ids)
  @connection.delete_relationship("/libraries/#{library_id}/relationships/data_elements", payload)
  nil
end

#remove_environment(library_id) ⇒ nil

Removes any assigned environment from a library.

Parameters:

  • library_id (String)

Returns:

  • (nil)


482
483
484
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 482

def remove_environment(library_id)
  delete_resource("/libraries/#{library_id}/relationships/environment")
end

#remove_extensions(library_id, extension_ids) ⇒ nil

Removes specific extensions from a library. Only the specified extensions are removed — others are preserved.

Parameters:

  • library_id (String)

    Adobe library ID

  • extension_ids (Array<String>)

    Adobe extension IDs to remove

Returns:

  • (nil)

Raises:



395
396
397
398
399
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 395

def remove_extensions(library_id, extension_ids)
  payload = build_relationship_payload('extensions', extension_ids)
  @connection.delete_relationship("/libraries/#{library_id}/relationships/extensions", payload)
  nil
end

#remove_rules(library_id, rule_ids) ⇒ nil

Removes specific rules from a library. Only the specified rules are removed — other rules are preserved.

Parameters:

  • library_id (String)

    Adobe library ID

  • rule_ids (Array<String>)

    Adobe rule IDs to remove

Returns:

  • (nil)

Raises:



253
254
255
256
257
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 253

def remove_rules(library_id, rule_ids)
  payload = build_relationship_payload('rules', rule_ids)
  @connection.delete_relationship("/libraries/#{library_id}/relationships/rules", payload)
  nil
end

#rule_relationships(library_id) ⇒ Hash, ...

Retrieves raw rule relationship linkage for a library.

Parameters:

  • library_id (String)

Returns:

  • (Hash, Array<Hash>, nil)


294
295
296
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 294

def rule_relationships(library_id)
  fetch_relationship("/libraries/#{library_id}/relationships/rules")
end

#rules(library_id) ⇒ Array<ReactorSDK::Resources::Rule>

Lists the rules currently assigned to a library.

Parameters:

  • library_id (String)

Returns:



284
285
286
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 284

def rules(library_id)
  list_resources("/libraries/#{library_id}/rules", Resources::Rule)
end

#set_data_elements(library_id, data_element_ids) ⇒ nil

Replaces the entire data elements list for a library. Any data element currently in the library that is NOT in data_element_ids is removed. Passing an empty array removes all data elements from the library.

Use with caution — this is a destructive operation.

Parameters:

  • library_id (String)

    Adobe library ID

  • data_element_ids (Array<String>)

    Complete new list of data element IDs

Returns:

  • (nil)

Raises:



343
344
345
346
347
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 343

def set_data_elements(library_id, data_element_ids)
  payload = build_relationship_payload('data_elements', data_element_ids)
  @connection.patch("/libraries/#{library_id}/relationships/data_elements", payload)
  nil
end

#set_extensions(library_id, extension_ids) ⇒ nil

Replaces the entire extensions list for a library. Any extension currently in the library that is NOT in extension_ids is removed. Passing an empty array removes all extensions.

Use with caution — this is a destructive operation.

Parameters:

  • library_id (String)

    Adobe library ID

  • extension_ids (Array<String>)

    Complete new list of extension IDs

Returns:

  • (nil)

Raises:



413
414
415
416
417
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 413

def set_extensions(library_id, extension_ids)
  payload = build_relationship_payload('extensions', extension_ids)
  @connection.patch("/libraries/#{library_id}/relationships/extensions", payload)
  nil
end

#set_rules(library_id, rule_ids) ⇒ nil

Replaces the entire rules list for a library. Any rule currently in the library that is NOT in rule_ids is removed. Passing an empty array removes all rules from the library.

Use with caution — this is a destructive operation. Prefer add_rules and remove_rules for incremental changes.

Parameters:

  • library_id (String)

    Adobe library ID

  • rule_ids (Array<String>)

    Complete new list of Adobe rule IDs

Returns:

  • (nil)

Raises:



272
273
274
275
276
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 272

def set_rules(library_id, rule_ids)
  payload = build_relationship_payload('rules', rule_ids)
  @connection.patch("/libraries/#{library_id}/relationships/rules", payload)
  nil
end

#transition(library_id, state:) ⇒ ReactorSDK::Resources::Library

Transitions a library to a new state in its workflow.

Valid transitions:

development -> submitted -> approved -> published
                        -> rejected -> development

Parameters:

  • library_id (String)

    Adobe library ID

  • state (String)

    Target state to transition to

Returns:

Raises:



500
501
502
503
504
505
506
507
508
509
510
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 500

def transition(library_id, state:)
  payload = {
    data: {
      id: library_id,
      type: 'libraries',
      meta: { action: normalize_transition_action(state) }
    }
  }
  response = @connection.patch("/libraries/#{library_id}", payload)
  @parser.parse(response['data'], Resources::Library)
end

#update(library_id, attributes) ⇒ ReactorSDK::Resources::Library

Updates a library’s attributes.

Parameters:

  • library_id (String)
  • attributes (Hash)

Returns:



196
197
198
199
200
201
202
203
204
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 196

def update(library_id, attributes)
  update_resource(
    "/libraries/#{library_id}",
    library_id,
    'libraries',
    Resources::Library,
    attributes: attributes
  )
end

#upstream_chain_for_resource(resource_or_id, library_id:, property_id:, resource_type: nil) ⇒ ReactorSDK::Resources::UpstreamChain

Resolves a single resource across the ordered upstream library chain.

This is the resource-level convenience wrapper built on top of upstream_libraries and find_with_resources. It allows callers to ask for upstream information directly from a rule, data element, or extension ID without hand-rolling the traversal loop.

The returned UpstreamChain object includes:

- the target library context
- the target resource and target revision_id when present
- one UpstreamChainEntry per upstream library, nearest first

Parameters:

  • resource_or_id (String, ReactorSDK::Resources::BaseResource)
  • library_id (String)

    Adobe library ID used as the comparison root

  • property_id (String)

    Adobe property ID containing the library chain

  • resource_type (String, nil) (defaults to: nil)

    Optional JSON:API type hint

Returns:



616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 616

def upstream_chain_for_resource(resource_or_id, library_id:, property_id:, resource_type: nil)
  resource_id = extract_resource_id(resource_or_id)
  target_library = find_with_resources(library_id)
  target_resource = target_library.all_resources.find { |resource| resource.id == resource_id }
  target_revision_id = target_library.resource_index[resource_id]

  entries = upstream_libraries(library_id, property_id: property_id).map do |library|
    build_upstream_chain_entry(library, resource_id)
  end

  Resources::UpstreamChain.new(
    resource_id: resource_id,
    resource_type: resource_type || extract_resource_type(resource_or_id) || target_resource&.type,
    property_id: property_id,
    target_library_id: library_id,
    target_resource: target_resource,
    target_revision_id: target_revision_id,
    entries: entries
  )
end

#upstream_libraries(library_id, property_id:) ⇒ Array<ReactorSDK::Resources::Library>

Returns the ordered list of libraries upstream of the given library.

Adobe Launch uses an environment hierarchy where changes flow upward: Personal Dev → Development → Staging → Production

“Upstream” means closer to Production. When a resource does not exist in the target library, the app walks this list in order to find the nearest upstream version to diff against.

Examples:

Target is Development → returns [staging_library, production_library]
Target is Staging     → returns [production_library]
Target is Production  → returns [] (nothing upstream)

Parameters:

  • library_id (String)

    Adobe library ID of the target library

  • property_id (String)

    Adobe property ID

Returns:

Raises:



580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 580

def upstream_libraries(library_id, property_id:)
  find(library_id)
  target_stage = fetch_library_stage(library_id)

  return [] if target_stage.nil?
  return [] if target_stage == 'production'

  upstream_stages = stages_above(target_stage)
  all_libraries   = list_for_property(property_id)

  upstream_stages.filter_map do |stage|
    all_libraries.find do |lib|
      fetch_library_stage(lib.id) == stage
    end
  end
end

#upstream_library(library_id) ⇒ ReactorSDK::Resources::Library

Retrieves the immediate upstream library configured for a library.

Parameters:

  • library_id (String)

Returns:



533
534
535
# File 'lib/reactor_sdk/endpoints/libraries.rb', line 533

def upstream_library(library_id)
  fetch_resource("/libraries/#{library_id}/upstream_library", Resources::Library)
end