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.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +19 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +281 -0
  5. data/lib/reactor_sdk/authentication.rb +137 -0
  6. data/lib/reactor_sdk/client.rb +186 -0
  7. data/lib/reactor_sdk/configuration.rb +102 -0
  8. data/lib/reactor_sdk/connection.rb +342 -0
  9. data/lib/reactor_sdk/endpoints/app_configurations.rb +42 -0
  10. data/lib/reactor_sdk/endpoints/audit_events.rb +64 -0
  11. data/lib/reactor_sdk/endpoints/base_endpoint.rb +207 -0
  12. data/lib/reactor_sdk/endpoints/builds.rb +62 -0
  13. data/lib/reactor_sdk/endpoints/callbacks.rb +38 -0
  14. data/lib/reactor_sdk/endpoints/companies.rb +42 -0
  15. data/lib/reactor_sdk/endpoints/data_elements.rb +251 -0
  16. data/lib/reactor_sdk/endpoints/environments.rb +174 -0
  17. data/lib/reactor_sdk/endpoints/extension_package_usage_authorizations.rb +51 -0
  18. data/lib/reactor_sdk/endpoints/extension_packages.rb +63 -0
  19. data/lib/reactor_sdk/endpoints/extensions.rb +181 -0
  20. data/lib/reactor_sdk/endpoints/hosts.rb +101 -0
  21. data/lib/reactor_sdk/endpoints/libraries.rb +872 -0
  22. data/lib/reactor_sdk/endpoints/notes.rb +11 -0
  23. data/lib/reactor_sdk/endpoints/profiles.rb +14 -0
  24. data/lib/reactor_sdk/endpoints/properties.rb +123 -0
  25. data/lib/reactor_sdk/endpoints/revisions.rb +102 -0
  26. data/lib/reactor_sdk/endpoints/rule_components.rb +218 -0
  27. data/lib/reactor_sdk/endpoints/rules.rb +240 -0
  28. data/lib/reactor_sdk/endpoints/search.rb +23 -0
  29. data/lib/reactor_sdk/endpoints/secrets.rb +76 -0
  30. data/lib/reactor_sdk/error.rb +115 -0
  31. data/lib/reactor_sdk/library_comparison_builder.rb +74 -0
  32. data/lib/reactor_sdk/library_snapshot_builder.rb +66 -0
  33. data/lib/reactor_sdk/paginator.rb +92 -0
  34. data/lib/reactor_sdk/rate_limiter.rb +96 -0
  35. data/lib/reactor_sdk/reference_extractor.rb +34 -0
  36. data/lib/reactor_sdk/resource_metadata.rb +73 -0
  37. data/lib/reactor_sdk/resource_normalizer.rb +90 -0
  38. data/lib/reactor_sdk/resources/app_configuration.rb +20 -0
  39. data/lib/reactor_sdk/resources/audit_event.rb +45 -0
  40. data/lib/reactor_sdk/resources/base_resource.rb +181 -0
  41. data/lib/reactor_sdk/resources/build.rb +64 -0
  42. data/lib/reactor_sdk/resources/callback.rb +16 -0
  43. data/lib/reactor_sdk/resources/company.rb +38 -0
  44. data/lib/reactor_sdk/resources/comprehensive_data_element.rb +28 -0
  45. data/lib/reactor_sdk/resources/comprehensive_extension.rb +30 -0
  46. data/lib/reactor_sdk/resources/comprehensive_resource.rb +31 -0
  47. data/lib/reactor_sdk/resources/comprehensive_rule.rb +26 -0
  48. data/lib/reactor_sdk/resources/comprehensive_upstream_chain.rb +50 -0
  49. data/lib/reactor_sdk/resources/comprehensive_upstream_chain_entry.rb +34 -0
  50. data/lib/reactor_sdk/resources/data_element.rb +108 -0
  51. data/lib/reactor_sdk/resources/environment.rb +45 -0
  52. data/lib/reactor_sdk/resources/extension.rb +66 -0
  53. data/lib/reactor_sdk/resources/extension_package.rb +49 -0
  54. data/lib/reactor_sdk/resources/extension_package_usage_authorization.rb +26 -0
  55. data/lib/reactor_sdk/resources/host.rb +68 -0
  56. data/lib/reactor_sdk/resources/library.rb +67 -0
  57. data/lib/reactor_sdk/resources/library_comparison.rb +72 -0
  58. data/lib/reactor_sdk/resources/library_comparison_entry.rb +144 -0
  59. data/lib/reactor_sdk/resources/library_snapshot.rb +118 -0
  60. data/lib/reactor_sdk/resources/library_snapshot_extension_index.rb +70 -0
  61. data/lib/reactor_sdk/resources/library_snapshot_index.rb +169 -0
  62. data/lib/reactor_sdk/resources/library_with_resources.rb +194 -0
  63. data/lib/reactor_sdk/resources/note.rb +37 -0
  64. data/lib/reactor_sdk/resources/profile.rb +22 -0
  65. data/lib/reactor_sdk/resources/property.rb +44 -0
  66. data/lib/reactor_sdk/resources/revision.rb +156 -0
  67. data/lib/reactor_sdk/resources/rule.rb +44 -0
  68. data/lib/reactor_sdk/resources/rule_component.rb +101 -0
  69. data/lib/reactor_sdk/resources/search_results.rb +28 -0
  70. data/lib/reactor_sdk/resources/secret.rb +17 -0
  71. data/lib/reactor_sdk/resources/upstream_chain.rb +80 -0
  72. data/lib/reactor_sdk/resources/upstream_chain_entry.rb +55 -0
  73. data/lib/reactor_sdk/response_parser.rb +160 -0
  74. data/lib/reactor_sdk/version.rb +5 -0
  75. data/lib/reactor_sdk.rb +79 -0
  76. data/reactor_sdk.gemspec +70 -0
  77. data/sig/reactor_sdk.rbs +346 -0
  78. metadata +293 -0
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # @file endpoints/environments.rb
5
+ # @description Endpoint group for Adobe Launch Environment resources.
6
+ #
7
+ # Environments map to deployment targets within a property.
8
+ # Each property has three built-in environments: development, staging,
9
+ # and production. Additional environments can be created for personal
10
+ # developer sandboxes — this is how LaunchGuard provisions per-developer
11
+ # workspaces.
12
+ #
13
+ # Important: the Reactor API requires a host relationship when creating
14
+ # an environment. Fetch the property's hosts first and pass the host_id
15
+ # to the create method. Most properties have exactly one Akamai host.
16
+ #
17
+ # Example:
18
+ # hosts = client.hosts.list_for_property(property_id)
19
+ # client.environments.create(
20
+ # property_id: property_id,
21
+ # name: "jsmith-dev",
22
+ # stage: "development",
23
+ # host_id: hosts.first.id
24
+ # )
25
+ #
26
+ # @domain Endpoints
27
+ # @see https://developer.adobe.com/experience-platform/documentation/tags/api/endpoints/environments/
28
+ #
29
+
30
+ module ReactorSDK
31
+ module Endpoints
32
+ class Environments < BaseEndpoint
33
+ ##
34
+ # Lists all environments for a given property.
35
+ # Follows pagination automatically — returns all environments.
36
+ #
37
+ # @param property_id [String] Adobe property ID
38
+ # @return [Array<ReactorSDK::Resources::Environment>]
39
+ # @raise [ReactorSDK::ResourceNotFoundError] if the property does not exist
40
+ #
41
+ def list_for_property(property_id)
42
+ list_resources("/properties/#{property_id}/environments", Resources::Environment)
43
+ end
44
+
45
+ ##
46
+ # Retrieves a single environment by its Adobe ID.
47
+ #
48
+ # @param environment_id [String] Adobe environment ID (format: "EN" + hex string)
49
+ # @return [ReactorSDK::Resources::Environment]
50
+ # @raise [ReactorSDK::ResourceNotFoundError] if the environment does not exist
51
+ #
52
+ def find(environment_id)
53
+ fetch_resource("/environments/#{environment_id}", Resources::Environment)
54
+ end
55
+
56
+ ##
57
+ # Creates a new environment within a property.
58
+ #
59
+ # Requires a host_id — fetch the property's hosts first:
60
+ # hosts = client.hosts.list_for_property(property_id)
61
+ # host_id = hosts.first.id
62
+ #
63
+ # Used by LaunchGuard to provision personal developer sandboxes
64
+ # when a new user joins an organisation.
65
+ #
66
+ # @param property_id [String] Adobe property ID
67
+ # @param name [String] Display name (e.g. "jsmith-dev")
68
+ # @param stage [String] One of: "development", "staging", "production"
69
+ # @param host_id [String] Adobe host ID — required by the Reactor API
70
+ # @return [ReactorSDK::Resources::Environment] The newly created environment
71
+ # @raise [ReactorSDK::UnprocessableEntityError] if attributes are invalid
72
+ # @raise [ReactorSDK::ConfigurationError] if host_id is blank
73
+ #
74
+ def create(property_id:, name:, host_id:, stage: 'development')
75
+ if host_id.nil? || host_id.strip.empty?
76
+ raise ConfigurationError,
77
+ 'host_id is required to create an environment. ' \
78
+ 'Fetch the property hosts first: client.hosts.list_for_property(property_id)'
79
+ end
80
+
81
+ create_resource(
82
+ "/properties/#{property_id}/environments",
83
+ 'environments',
84
+ Resources::Environment,
85
+ attributes: { name: name, stage: stage },
86
+ relationships: {
87
+ host: {
88
+ data: { id: host_id, type: 'hosts' }
89
+ }
90
+ }
91
+ )
92
+ end
93
+
94
+ ##
95
+ # Updates an existing environment.
96
+ #
97
+ # @param environment_id [String] Adobe environment ID
98
+ # @param attributes [Hash] Fields to update
99
+ # @return [ReactorSDK::Resources::Environment]
100
+ #
101
+ def update(environment_id, attributes)
102
+ update_resource(
103
+ "/environments/#{environment_id}",
104
+ environment_id,
105
+ 'environments',
106
+ Resources::Environment,
107
+ attributes: attributes
108
+ )
109
+ end
110
+
111
+ ##
112
+ # Retrieves the host assigned to an environment.
113
+ #
114
+ # @param environment_id [String] Adobe environment ID
115
+ # @return [ReactorSDK::Resources::Host]
116
+ #
117
+ def host(environment_id)
118
+ fetch_resource("/environments/#{environment_id}/host", Resources::Host)
119
+ end
120
+
121
+ ##
122
+ # Retrieves the raw host relationship linkage for an environment.
123
+ #
124
+ # @param environment_id [String] Adobe environment ID
125
+ # @return [Hash, nil]
126
+ #
127
+ def host_relationship(environment_id)
128
+ fetch_relationship("/environments/#{environment_id}/relationships/host")
129
+ end
130
+
131
+ ##
132
+ # Retrieves the library currently assigned to an environment.
133
+ #
134
+ # @param environment_id [String] Adobe environment ID
135
+ # @return [ReactorSDK::Resources::Library]
136
+ #
137
+ def library(environment_id)
138
+ fetch_resource("/environments/#{environment_id}/library", Resources::Library)
139
+ end
140
+
141
+ ##
142
+ # Retrieves the property that owns an environment.
143
+ #
144
+ # @param environment_id [String] Adobe environment ID
145
+ # @return [ReactorSDK::Resources::Property]
146
+ #
147
+ def property(environment_id)
148
+ fetch_resource("/environments/#{environment_id}/property", Resources::Property)
149
+ end
150
+
151
+ ##
152
+ # Lists builds produced for an environment.
153
+ #
154
+ # @param environment_id [String] Adobe environment ID
155
+ # @return [Array<ReactorSDK::Resources::Build>]
156
+ #
157
+ def builds(environment_id)
158
+ list_resources("/environments/#{environment_id}/builds", Resources::Build)
159
+ end
160
+
161
+ ##
162
+ # Deletes an environment permanently.
163
+ # Only non-built-in environments (personal sandboxes) should be deleted.
164
+ #
165
+ # @param environment_id [String] Adobe environment ID
166
+ # @return [nil]
167
+ # @raise [ReactorSDK::ResourceNotFoundError] if the environment does not exist
168
+ #
169
+ def delete(environment_id)
170
+ delete_resource("/environments/#{environment_id}")
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReactorSDK
4
+ module Endpoints
5
+ class ExtensionPackageUsageAuthorizations < BaseEndpoint
6
+ def list
7
+ list_resources(
8
+ '/extension_package_usage_authorizations',
9
+ Resources::ExtensionPackageUsageAuthorization
10
+ )
11
+ end
12
+
13
+ def list_for_package(extension_package_id)
14
+ list_resources(
15
+ "/extension_packages/#{extension_package_id}/extension_package_usage_authorizations",
16
+ Resources::ExtensionPackageUsageAuthorization
17
+ )
18
+ end
19
+
20
+ def create(extension_package_id:, authorized_org_id:)
21
+ create_resource(
22
+ "/extension_packages/#{extension_package_id}/extension_package_usage_authorizations",
23
+ 'extension_package_usage_authorizations',
24
+ Resources::ExtensionPackageUsageAuthorization,
25
+ attributes: { authorized_org_id: authorized_org_id }
26
+ )
27
+ end
28
+
29
+ def update(authorization_id, state:)
30
+ update_resource(
31
+ "/extension_package_usage_authorizations/#{authorization_id}",
32
+ authorization_id,
33
+ 'extension_package_usage_authorizations',
34
+ Resources::ExtensionPackageUsageAuthorization,
35
+ attributes: { state: state }
36
+ )
37
+ end
38
+
39
+ def delete(authorization_id)
40
+ delete_resource("/extension_package_usage_authorizations/#{authorization_id}")
41
+ end
42
+
43
+ def extension_package(authorization_id)
44
+ fetch_resource(
45
+ "/extension_package_usage_authorizations/#{authorization_id}/extension_package",
46
+ Resources::ExtensionPackage
47
+ )
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReactorSDK
4
+ module Endpoints
5
+ class ExtensionPackages < BaseEndpoint
6
+ def list(params: {})
7
+ list_resources('/extension_packages', Resources::ExtensionPackage, params: params)
8
+ end
9
+
10
+ def find(extension_package_id)
11
+ fetch_resource("/extension_packages/#{extension_package_id}", Resources::ExtensionPackage)
12
+ end
13
+
14
+ def create(package_path:)
15
+ response = @connection.post_multipart('/extension_packages', file_path: package_path)
16
+ @parser.parse(response['data'], Resources::ExtensionPackage, response: response)
17
+ end
18
+
19
+ def update(extension_package_id, package_path:)
20
+ response = @connection.post_multipart(
21
+ "/extension_packages/#{extension_package_id}",
22
+ file_path: package_path
23
+ )
24
+ @parser.parse(response['data'], Resources::ExtensionPackage, response: response)
25
+ end
26
+
27
+ def private_release(extension_package_id)
28
+ transition(extension_package_id, action: 'release_private')
29
+ end
30
+
31
+ def discontinue(extension_package_id)
32
+ transition(extension_package_id, action: 'discontinue')
33
+ end
34
+
35
+ def versions(extension_package_id)
36
+ list_resources(
37
+ "/extension_packages/#{extension_package_id}/versions",
38
+ Resources::ExtensionPackage
39
+ )
40
+ end
41
+
42
+ def usage_authorizations(extension_package_id)
43
+ list_resources(
44
+ "/extension_packages/#{extension_package_id}/extension_package_usage_authorizations",
45
+ Resources::ExtensionPackageUsageAuthorization
46
+ )
47
+ end
48
+
49
+ private
50
+
51
+ def transition(extension_package_id, action:)
52
+ update_resource(
53
+ "/extension_packages/#{extension_package_id}",
54
+ extension_package_id,
55
+ 'extension_packages',
56
+ Resources::ExtensionPackage,
57
+ attributes: {},
58
+ meta: { action: action }
59
+ )
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # @file endpoints/extensions.rb
5
+ # @description Endpoint group for Adobe Launch Extension resources.
6
+ #
7
+ # Extensions provide the delegates (conditions, actions, data element
8
+ # types) available within a property. The Core extension is always
9
+ # present. Third-party extensions are installed separately.
10
+ #
11
+ # Important: extensions must be revised before they can be added to
12
+ # a library. Call revise(extension_id) before libraries.add_extensions.
13
+ #
14
+ # @domain Endpoints
15
+ # @see https://developer.adobe.com/experience-platform/documentation/tags/api/endpoints/extensions/
16
+ #
17
+
18
+ module ReactorSDK
19
+ module Endpoints
20
+ class Extensions < BaseEndpoint
21
+ ##
22
+ # Lists all extensions installed in a given property.
23
+ # Follows pagination automatically — returns all extensions.
24
+ #
25
+ # @param property_id [String] Adobe property ID
26
+ # @return [Array<ReactorSDK::Resources::Extension>]
27
+ # @raise [ReactorSDK::ResourceNotFoundError] if the property does not exist
28
+ #
29
+ def list_for_property(property_id)
30
+ records = @paginator.all("/properties/#{property_id}/extensions")
31
+ records.map { |r| @parser.parse(r, Resources::Extension) }
32
+ end
33
+
34
+ ##
35
+ # Retrieves a single extension by its Adobe ID.
36
+ #
37
+ # @param extension_id [String] Adobe extension ID (format: "EX" + hex string)
38
+ # @return [ReactorSDK::Resources::Extension]
39
+ # @raise [ReactorSDK::ResourceNotFoundError] if the extension does not exist
40
+ #
41
+ def find(extension_id)
42
+ response = @connection.get("/extensions/#{extension_id}")
43
+ @parser.parse(response['data'], Resources::Extension)
44
+ end
45
+
46
+ ##
47
+ # Creates an extension within a property.
48
+ #
49
+ # @param property_id [String]
50
+ # @param attributes [Hash]
51
+ # @param relationships [Hash]
52
+ # @return [ReactorSDK::Resources::Extension]
53
+ #
54
+ def create(property_id:, attributes:, relationships:)
55
+ create_resource(
56
+ "/properties/#{property_id}/extensions",
57
+ 'extensions',
58
+ Resources::Extension,
59
+ attributes: attributes,
60
+ relationships: relationships
61
+ )
62
+ end
63
+
64
+ ##
65
+ # Revises an extension so it can be added to a library.
66
+ #
67
+ # Adobe Launch requires every resource to be explicitly revised before
68
+ # it can be added to a library.
69
+ #
70
+ # Always call revise before libraries.add_extensions.
71
+ #
72
+ # @param extension_id [String] Adobe extension ID
73
+ # @return [ReactorSDK::Resources::Extension] The revised extension
74
+ # @raise [ReactorSDK::ResourceNotFoundError] if the extension does not exist
75
+ #
76
+ def revise(extension_id)
77
+ update_resource(
78
+ "/extensions/#{extension_id}",
79
+ extension_id,
80
+ 'extensions',
81
+ Resources::Extension,
82
+ attributes: {},
83
+ meta: { action: 'revise' }
84
+ )
85
+ end
86
+
87
+ def delete(extension_id)
88
+ delete_resource("/extensions/#{extension_id}")
89
+ end
90
+
91
+ def extension_package(extension_id)
92
+ fetch_resource("/extensions/#{extension_id}/extension_package", Resources::ExtensionPackage)
93
+ end
94
+
95
+ def libraries(extension_id)
96
+ list_resources("/extensions/#{extension_id}/libraries", Resources::Library)
97
+ end
98
+
99
+ def property(extension_id)
100
+ fetch_resource("/extensions/#{extension_id}/property", Resources::Property)
101
+ end
102
+
103
+ def origin(extension_id)
104
+ fetch_resource("/extensions/#{extension_id}/origin", Resources::Extension)
105
+ end
106
+
107
+ ##
108
+ # Resolves the extension across the ordered upstream library chain.
109
+ #
110
+ # @param extension_or_id [String, ReactorSDK::Resources::Extension]
111
+ # @param library_id [String] Adobe library ID used as the comparison root
112
+ # @param property_id [String] Adobe property ID containing the library chain
113
+ # @return [ReactorSDK::Resources::UpstreamChain]
114
+ #
115
+ def upstream_chain(extension_or_id, library_id:, property_id:)
116
+ libraries_endpoint.upstream_chain_for_resource(
117
+ extension_or_id,
118
+ library_id: library_id,
119
+ property_id: property_id,
120
+ resource_type: 'extensions'
121
+ )
122
+ end
123
+
124
+ ##
125
+ # Fetches the extension from a library-context review snapshot together
126
+ # with dependent resources and normalized review payload.
127
+ #
128
+ # @param extension_id [String]
129
+ # @param library_id [String]
130
+ # @param property_id [String]
131
+ # @return [ReactorSDK::Resources::ComprehensiveExtension]
132
+ #
133
+ def find_comprehensive(extension_id, library_id:, property_id:)
134
+ snapshot = libraries_endpoint.find_snapshot(library_id, property_id: property_id)
135
+ comprehensive = snapshot.comprehensive_resource(extension_id, resource_type: 'extensions')
136
+ unless comprehensive
137
+ raise ReactorSDK::ResourceNotFoundError,
138
+ "Extension #{extension_id} was not found in library #{library_id}"
139
+ end
140
+
141
+ comprehensive
142
+ end
143
+
144
+ ##
145
+ # Resolves the extension across the ordered upstream chain using
146
+ # snapshot-aware comprehensive review objects.
147
+ #
148
+ # @param extension_or_id [String, ReactorSDK::Resources::Extension]
149
+ # @param library_id [String]
150
+ # @param property_id [String]
151
+ # @return [ReactorSDK::Resources::ComprehensiveUpstreamChain]
152
+ #
153
+ def comprehensive_upstream_chain(extension_or_id, library_id:, property_id:)
154
+ libraries_endpoint.comprehensive_upstream_chain_for_resource(
155
+ extension_or_id,
156
+ library_id: library_id,
157
+ property_id: property_id,
158
+ resource_type: 'extensions'
159
+ )
160
+ end
161
+
162
+ def list_notes(extension_id)
163
+ list_notes_for_path("/extensions/#{extension_id}/notes")
164
+ end
165
+
166
+ def create_note(extension_id, text)
167
+ create_note_for_path("/extensions/#{extension_id}/notes", text)
168
+ end
169
+
170
+ private
171
+
172
+ def libraries_endpoint
173
+ @libraries_endpoint ||= Endpoints::Libraries.new(
174
+ connection: @connection,
175
+ paginator: @paginator,
176
+ parser: @parser
177
+ )
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # @file endpoints/hosts.rb
5
+ # @description Endpoint group for Adobe Launch Host resources.
6
+ #
7
+ # Hosts define where Adobe Launch builds are deployed. A host ID is
8
+ # required when creating an environment — fetch the property's hosts
9
+ # first and pass the ID to environments.create.
10
+ #
11
+ # Most properties have exactly one Adobe-managed Akamai host created
12
+ # automatically. Use list_for_property to retrieve it.
13
+ #
14
+ # @domain Endpoints
15
+ # @see https://developer.adobe.com/experience-platform/documentation/tags/api/endpoints/hosts/
16
+ #
17
+
18
+ module ReactorSDK
19
+ module Endpoints
20
+ class Hosts < BaseEndpoint
21
+ ##
22
+ # Lists all hosts for a given property.
23
+ # Follows pagination automatically — returns all hosts.
24
+ #
25
+ # Most properties have exactly one host — the Adobe-managed Akamai host.
26
+ # Call this before creating an environment to obtain the host ID.
27
+ #
28
+ # @param property_id [String] Adobe property ID
29
+ # @return [Array<ReactorSDK::Resources::Host>]
30
+ # @raise [ReactorSDK::ResourceNotFoundError] if the property does not exist
31
+ #
32
+ def list_for_property(property_id)
33
+ list_resources("/properties/#{property_id}/hosts", Resources::Host)
34
+ end
35
+
36
+ ##
37
+ # Retrieves a single host by its Adobe ID.
38
+ #
39
+ # @param host_id [String] Adobe host ID (format: "HT" + hex string)
40
+ # @return [ReactorSDK::Resources::Host]
41
+ # @raise [ReactorSDK::ResourceNotFoundError] if the host does not exist
42
+ #
43
+ def find(host_id)
44
+ fetch_resource("/hosts/#{host_id}", Resources::Host)
45
+ end
46
+
47
+ ##
48
+ # Creates a host within a property.
49
+ #
50
+ # @param property_id [String] Adobe property ID
51
+ # @param attributes [Hash] Host attributes exactly as accepted by Reactor
52
+ # @return [ReactorSDK::Resources::Host]
53
+ #
54
+ def create(property_id:, attributes:)
55
+ create_resource(
56
+ "/properties/#{property_id}/hosts",
57
+ 'hosts',
58
+ Resources::Host,
59
+ attributes: attributes
60
+ )
61
+ end
62
+
63
+ ##
64
+ # Updates an existing host.
65
+ #
66
+ # @param host_id [String] Adobe host ID
67
+ # @param attributes [Hash] Fields to update
68
+ # @return [ReactorSDK::Resources::Host]
69
+ #
70
+ def update(host_id, attributes)
71
+ update_resource(
72
+ "/hosts/#{host_id}",
73
+ host_id,
74
+ 'hosts',
75
+ Resources::Host,
76
+ attributes: attributes
77
+ )
78
+ end
79
+
80
+ ##
81
+ # Deletes a host permanently.
82
+ #
83
+ # @param host_id [String] Adobe host ID
84
+ # @return [nil]
85
+ #
86
+ def delete(host_id)
87
+ delete_resource("/hosts/#{host_id}")
88
+ end
89
+
90
+ ##
91
+ # Retrieves the property that owns a host.
92
+ #
93
+ # @param host_id [String] Adobe host ID
94
+ # @return [ReactorSDK::Resources::Property]
95
+ #
96
+ def property(host_id)
97
+ fetch_resource("/hosts/#{host_id}/property", Resources::Property)
98
+ end
99
+ end
100
+ end
101
+ end