patch_retention 0.3.1 → 0.4.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 +4 -4
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +14 -29
- data/README.md +1 -0
- data/lib/patch_retention/calendar_items.rb +6 -8
- data/lib/patch_retention/contacts/update.rb +1 -1
- data/lib/patch_retention/memberships.rb +8 -9
- data/lib/patch_retention/products.rb +5 -7
- data/lib/patch_retention/util.rb +10 -11
- data/lib/patch_retention/version.rb +1 -1
- data/lib/patch_retention.rb +1 -0
- data/patch_retention.gemspec +4 -4
- metadata +8 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a4e08ff07a6967ecf42cb39dc2996ac46076344f46ed37c546f8dc2f676da7bb
|
|
4
|
+
data.tar.gz: bc86913cf3b560d6eefe94fa722996b7d5442de0200d1060bb5607c1384ad492
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 931fdeb3e17af3b102cd5cf749530c1c3f8601e3ac9a33dd7e74af53618b0a5d95a68366ec694280052263d06d28f6e073efb11df3a3f1896df69a6dd86b0a20
|
|
7
|
+
data.tar.gz: 1a8e1c80c352bb5e936abe07f922e688e63559e4670d98c2e2e7273f91124e0a16317d946e82638066898a349bf17582c94832a7d5c4a70dddc7b46127bb4c2a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.4.0] - 2025-12-30
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- **BREAKING**: Upgraded Faraday from 1.x to 2.x (`~> 2.7`)
|
|
7
|
+
- Simplified HTTP request/response handling using Faraday 2.x JSON middleware
|
|
8
|
+
- Refactored `util.rb` to handle pre-parsed JSON responses
|
|
9
|
+
|
|
10
|
+
### Security
|
|
11
|
+
- Fixed rexml security vulnerability (CVE-2025-58767) by requiring version >= 3.4.2
|
|
12
|
+
|
|
13
|
+
## [0.3.2] - 2025-01-19
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- Added `next_billing_at` field support to `Memberships.create` method for setting the next billing date
|
|
17
|
+
|
|
3
18
|
## [0.3.1] - 2025-09-04
|
|
4
19
|
|
|
5
20
|
### Added
|
data/Gemfile.lock
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
patch_retention (0.
|
|
5
|
-
faraday (~>
|
|
4
|
+
patch_retention (0.4.0)
|
|
5
|
+
faraday (~> 2.7)
|
|
6
6
|
zeitwerk (~> 2.6)
|
|
7
7
|
|
|
8
8
|
GEM
|
|
@@ -23,34 +23,19 @@ GEM
|
|
|
23
23
|
rexml
|
|
24
24
|
diff-lcs (1.5.0)
|
|
25
25
|
dotenv (2.8.1)
|
|
26
|
-
faraday (
|
|
27
|
-
faraday-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
faraday-net_http (~> 1.0)
|
|
33
|
-
faraday-net_http_persistent (~> 1.0)
|
|
34
|
-
faraday-patron (~> 1.0)
|
|
35
|
-
faraday-rack (~> 1.0)
|
|
36
|
-
faraday-retry (~> 1.0)
|
|
37
|
-
ruby2_keywords (>= 0.0.4)
|
|
38
|
-
faraday-em_http (1.0.0)
|
|
39
|
-
faraday-em_synchrony (1.0.1)
|
|
40
|
-
faraday-excon (1.1.0)
|
|
41
|
-
faraday-httpclient (1.0.1)
|
|
42
|
-
faraday-multipart (1.1.1)
|
|
43
|
-
multipart-post (~> 2.0)
|
|
44
|
-
faraday-net_http (1.0.2)
|
|
45
|
-
faraday-net_http_persistent (1.2.0)
|
|
46
|
-
faraday-patron (1.0.0)
|
|
47
|
-
faraday-rack (1.0.0)
|
|
48
|
-
faraday-retry (1.0.3)
|
|
26
|
+
faraday (2.14.0)
|
|
27
|
+
faraday-net_http (>= 2.0, < 3.5)
|
|
28
|
+
json
|
|
29
|
+
logger
|
|
30
|
+
faraday-net_http (3.4.2)
|
|
31
|
+
net-http (~> 0.5)
|
|
49
32
|
hashdiff (1.2.0)
|
|
50
33
|
json (2.7.0)
|
|
51
34
|
language_server-protocol (3.17.0.3)
|
|
35
|
+
logger (1.7.0)
|
|
52
36
|
method_source (1.0.0)
|
|
53
|
-
|
|
37
|
+
net-http (0.9.1)
|
|
38
|
+
uri (>= 0.11.1)
|
|
54
39
|
parallel (1.23.0)
|
|
55
40
|
parser (3.2.2.4)
|
|
56
41
|
ast (~> 2.4.1)
|
|
@@ -63,7 +48,7 @@ GEM
|
|
|
63
48
|
rainbow (3.1.1)
|
|
64
49
|
rake (13.1.0)
|
|
65
50
|
regexp_parser (2.8.2)
|
|
66
|
-
rexml (3.4.
|
|
51
|
+
rexml (3.4.4)
|
|
67
52
|
rspec (3.12.0)
|
|
68
53
|
rspec-core (~> 3.12.0)
|
|
69
54
|
rspec-expectations (~> 3.12.0)
|
|
@@ -93,9 +78,9 @@ GEM
|
|
|
93
78
|
rubocop-shopify (2.15.1)
|
|
94
79
|
rubocop (~> 1.51)
|
|
95
80
|
ruby-progressbar (1.13.0)
|
|
96
|
-
ruby2_keywords (0.0.5)
|
|
97
81
|
thor (1.4.0)
|
|
98
82
|
unicode-display_width (2.5.0)
|
|
83
|
+
uri (1.1.1)
|
|
99
84
|
vcr (6.3.1)
|
|
100
85
|
base64
|
|
101
86
|
webmock (3.25.1)
|
|
@@ -115,7 +100,7 @@ DEPENDENCIES
|
|
|
115
100
|
patch_retention!
|
|
116
101
|
pry
|
|
117
102
|
rake (~> 13.0)
|
|
118
|
-
rexml (>= 3.
|
|
103
|
+
rexml (>= 3.4.2)
|
|
119
104
|
rspec (~> 3.0)
|
|
120
105
|
rubocop (~> 1.21)
|
|
121
106
|
rubocop-shopify (~> 2.15)
|
data/README.md
CHANGED
|
@@ -278,6 +278,7 @@ membership = PatchRetention::Memberships.create(
|
|
|
278
278
|
product_id: "65de5xxxxxxxxxxxxx", # Required, ID of the product (e.g., from product creation)
|
|
279
279
|
start_at: Time.now.xmlschema, # Optional, ISO8601 timestamp
|
|
280
280
|
end_at: (Time.now + 30*24*60*60).xmlschema, # Optional, ISO8601 timestamp (e.g., 30 days from now)
|
|
281
|
+
next_billing_at: (Time.now + 7*24*60*60).xmlschema, # Optional, ISO8601 timestamp for next billing date
|
|
281
282
|
external_id: "MEM123", # Optional
|
|
282
283
|
data: {
|
|
283
284
|
"is_trial" => true,
|
|
@@ -19,11 +19,10 @@ module PatchRetention
|
|
|
19
19
|
payload[:tags] = tags if tags
|
|
20
20
|
|
|
21
21
|
response = PatchRetention.connection(config).post("/v2/calendar_items") do |req|
|
|
22
|
-
req.body = payload
|
|
23
|
-
req.headers["Content-Type"] = "application/json"
|
|
22
|
+
req.body = payload
|
|
24
23
|
end
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
response.body
|
|
27
26
|
rescue Faraday::Error => e
|
|
28
27
|
raise Error, "Failed to create calendar item: #{e.message}"
|
|
29
28
|
end
|
|
@@ -40,11 +39,10 @@ module PatchRetention
|
|
|
40
39
|
payload[:tags] = tags if tags
|
|
41
40
|
|
|
42
41
|
response = PatchRetention.connection(config).patch("/v2/calendar_items/#{calendar_item_id}") do |req|
|
|
43
|
-
req.body = payload
|
|
44
|
-
req.headers["Content-Type"] = "application/json"
|
|
42
|
+
req.body = payload
|
|
45
43
|
end
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
response.body
|
|
48
46
|
rescue Faraday::Error => e
|
|
49
47
|
raise Error, "Failed to update calendar item: #{e.message}"
|
|
50
48
|
end
|
|
@@ -52,7 +50,7 @@ module PatchRetention
|
|
|
52
50
|
def find(calendar_item_id:, config: nil)
|
|
53
51
|
response = PatchRetention.connection(config).get("/v2/calendar_items/#{calendar_item_id}")
|
|
54
52
|
|
|
55
|
-
|
|
53
|
+
response.body
|
|
56
54
|
rescue Faraday::Error => e
|
|
57
55
|
raise Error, "Failed to find calendar item: #{e.message}"
|
|
58
56
|
end
|
|
@@ -77,7 +75,7 @@ module PatchRetention
|
|
|
77
75
|
|
|
78
76
|
response = PatchRetention.connection(config).get("/v2/calendar_items", params)
|
|
79
77
|
|
|
80
|
-
|
|
78
|
+
response.body
|
|
81
79
|
rescue Faraday::Error => e
|
|
82
80
|
raise Error, "Failed to retrieve calendar items: #{e.message}"
|
|
83
81
|
end
|
|
@@ -7,7 +7,7 @@ module PatchRetention::Contacts::Update
|
|
|
7
7
|
def call(id, contact_params, config = nil)
|
|
8
8
|
raise_error_if_present do
|
|
9
9
|
PatchRetention.connection(config).put("#{PatchRetention::Contacts::API_PATH}/#{id}") do |req|
|
|
10
|
-
req.body = contact_params
|
|
10
|
+
req.body = contact_params
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -3,24 +3,24 @@
|
|
|
3
3
|
module PatchRetention
|
|
4
4
|
class Memberships
|
|
5
5
|
class << self
|
|
6
|
-
def create(contact_id:, product_id:, start_at: nil, end_at: nil,
|
|
7
|
-
config: nil)
|
|
6
|
+
def create(contact_id:, product_id:, start_at: nil, end_at: nil, next_billing_at: nil, external_id: nil,
|
|
7
|
+
tags: nil, data: nil, config: nil)
|
|
8
8
|
payload = {
|
|
9
9
|
contact_id: contact_id,
|
|
10
10
|
product_id: product_id,
|
|
11
11
|
}
|
|
12
12
|
payload[:start_at] = start_at if start_at
|
|
13
13
|
payload[:end_at] = end_at if end_at
|
|
14
|
+
payload[:next_billing_at] = next_billing_at if next_billing_at
|
|
14
15
|
payload[:external_id] = external_id if external_id
|
|
15
16
|
payload[:tags] = tags if tags
|
|
16
17
|
payload[:data] = data if data
|
|
17
18
|
|
|
18
19
|
response = PatchRetention.connection(config).post("/v2/memberships") do |req|
|
|
19
|
-
req.body = payload
|
|
20
|
-
req.headers["Content-Type"] = "application/json"
|
|
20
|
+
req.body = payload
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
response.body
|
|
24
24
|
rescue Faraday::Error => e
|
|
25
25
|
# You might want to handle different types of Faraday errors differently
|
|
26
26
|
# or raise a custom error class
|
|
@@ -38,11 +38,10 @@ module PatchRetention
|
|
|
38
38
|
payload[:status] = status if status
|
|
39
39
|
|
|
40
40
|
response = PatchRetention.connection(config).patch("/v2/memberships/#{membership_id}") do |req|
|
|
41
|
-
req.body = payload
|
|
42
|
-
req.headers["Content-Type"] = "application/json"
|
|
41
|
+
req.body = payload
|
|
43
42
|
end
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
response.body
|
|
46
45
|
rescue Faraday::Error => e
|
|
47
46
|
raise Error, "Failed to update membership: #{e.message}"
|
|
48
47
|
end
|
|
@@ -50,7 +49,7 @@ module PatchRetention
|
|
|
50
49
|
def find(membership_id:, config: nil)
|
|
51
50
|
response = PatchRetention.connection(config).get("/v2/memberships/#{membership_id}")
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
response.body
|
|
54
53
|
rescue Faraday::Error => e
|
|
55
54
|
raise Error, "Failed to find membership: #{e.message}"
|
|
56
55
|
end
|
|
@@ -17,11 +17,10 @@ module PatchRetention
|
|
|
17
17
|
payload[:external_data] = external_data if external_data
|
|
18
18
|
|
|
19
19
|
response = PatchRetention.connection(config).post("/v2/products") do |req|
|
|
20
|
-
req.body = payload
|
|
21
|
-
req.headers["Content-Type"] = "application/json"
|
|
20
|
+
req.body = payload
|
|
22
21
|
end
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
response.body
|
|
25
24
|
rescue Faraday::Error => e
|
|
26
25
|
# You might want to handle different types of Faraday errors differently
|
|
27
26
|
# or raise a custom error class
|
|
@@ -41,11 +40,10 @@ module PatchRetention
|
|
|
41
40
|
payload[:external_data] = external_data if external_data
|
|
42
41
|
|
|
43
42
|
response = PatchRetention.connection(config).patch("/v2/products/#{product_id}") do |req|
|
|
44
|
-
req.body = payload
|
|
45
|
-
req.headers["Content-Type"] = "application/json"
|
|
43
|
+
req.body = payload
|
|
46
44
|
end
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
response.body
|
|
49
47
|
rescue Faraday::Error => e
|
|
50
48
|
raise Error, "Failed to update product: #{e.message}"
|
|
51
49
|
end
|
|
@@ -53,7 +51,7 @@ module PatchRetention
|
|
|
53
51
|
def find(product_id:, config: nil)
|
|
54
52
|
response = PatchRetention.connection(config).get("/v2/products/#{product_id}")
|
|
55
53
|
|
|
56
|
-
|
|
54
|
+
response.body
|
|
57
55
|
rescue Faraday::Error => e
|
|
58
56
|
raise Error, "Failed to find product: #{e.message}"
|
|
59
57
|
end
|
data/lib/patch_retention/util.rb
CHANGED
|
@@ -11,24 +11,23 @@ module PatchRetention
|
|
|
11
11
|
response = yield
|
|
12
12
|
raise PatchRetention::Error, parse_error_message(response) unless response.status.between?(200, 206)
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
true
|
|
14
|
+
case response.body
|
|
15
|
+
when Hash, Array then response.body
|
|
16
|
+
else true
|
|
18
17
|
end
|
|
19
18
|
end
|
|
20
19
|
|
|
21
|
-
#
|
|
22
|
-
# Raises a PatchRetention::Error if the response status is 502 and the body is blank.
|
|
20
|
+
# Extracts error message from the response.
|
|
23
21
|
# @param response [Object] The response to parse the error message from.
|
|
24
22
|
# @return [String] The error message parsed from the response body.
|
|
25
23
|
def parse_error_message(response)
|
|
26
|
-
if response.
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
if response.body.is_a?(Hash) && response.body["error"]
|
|
25
|
+
response.body["error"]
|
|
26
|
+
elsif response.status == 502
|
|
27
|
+
"Internal Server Error: Patch API"
|
|
28
|
+
else
|
|
29
|
+
"Request failed with status #{response.status}"
|
|
29
30
|
end
|
|
30
|
-
|
|
31
|
-
JSON.parse(response.body)["error"]
|
|
32
31
|
end
|
|
33
32
|
end
|
|
34
33
|
end
|
data/lib/patch_retention.rb
CHANGED
data/patch_retention.gemspec
CHANGED
|
@@ -5,8 +5,8 @@ require_relative "lib/patch_retention/version"
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = "patch_retention"
|
|
7
7
|
spec.version = PatchRetention::VERSION
|
|
8
|
-
spec.authors = ["Playbypoint", "Gerardo Ortega"]
|
|
9
|
-
spec.email = ["webmaster@playbypoint.com", "g3ortega@gmail.com"]
|
|
8
|
+
spec.authors = ["Playbypoint", "Gerardo Ortega", "Segundo Rebaza"]
|
|
9
|
+
spec.email = ["webmaster@playbypoint.com", "g3ortega@gmail.com", "alvaro.rp1593@gmail.com"]
|
|
10
10
|
|
|
11
11
|
spec.summary = "Patch Retention API wrapper."
|
|
12
12
|
spec.description = "Patch Retention API wrapper."
|
|
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
|
32
32
|
spec.require_paths = ["lib"]
|
|
33
33
|
|
|
34
34
|
# Runtime dependencies
|
|
35
|
-
spec.add_dependency("faraday", "~>
|
|
35
|
+
spec.add_dependency("faraday", "~> 2.7")
|
|
36
36
|
spec.add_dependency("zeitwerk", "~> 2.6")
|
|
37
37
|
|
|
38
38
|
# Development dependencies
|
|
@@ -50,7 +50,7 @@ Gem::Specification.new do |spec|
|
|
|
50
50
|
spec.add_development_dependency("webmock", "~> 3.0")
|
|
51
51
|
|
|
52
52
|
# Security update for rexml
|
|
53
|
-
spec.add_development_dependency("rexml", ">= 3.
|
|
53
|
+
spec.add_development_dependency("rexml", ">= 3.4.2")
|
|
54
54
|
|
|
55
55
|
# For more information and examples about making a new gem, check out our
|
|
56
56
|
# guide at: https://bundler.io/guides/creating_gem.html
|
metadata
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: patch_retention
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Playbypoint
|
|
8
8
|
- Gerardo Ortega
|
|
9
|
+
- Segundo Rebaza
|
|
9
10
|
autorequire:
|
|
10
11
|
bindir: exe
|
|
11
12
|
cert_chain: []
|
|
12
|
-
date: 2025-
|
|
13
|
+
date: 2025-12-30 00:00:00.000000000 Z
|
|
13
14
|
dependencies:
|
|
14
15
|
- !ruby/object:Gem::Dependency
|
|
15
16
|
name: faraday
|
|
@@ -17,14 +18,14 @@ dependencies:
|
|
|
17
18
|
requirements:
|
|
18
19
|
- - "~>"
|
|
19
20
|
- !ruby/object:Gem::Version
|
|
20
|
-
version: '
|
|
21
|
+
version: '2.7'
|
|
21
22
|
type: :runtime
|
|
22
23
|
prerelease: false
|
|
23
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
24
25
|
requirements:
|
|
25
26
|
- - "~>"
|
|
26
27
|
- !ruby/object:Gem::Version
|
|
27
|
-
version: '
|
|
28
|
+
version: '2.7'
|
|
28
29
|
- !ruby/object:Gem::Dependency
|
|
29
30
|
name: zeitwerk
|
|
30
31
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -213,18 +214,19 @@ dependencies:
|
|
|
213
214
|
requirements:
|
|
214
215
|
- - ">="
|
|
215
216
|
- !ruby/object:Gem::Version
|
|
216
|
-
version: 3.
|
|
217
|
+
version: 3.4.2
|
|
217
218
|
type: :development
|
|
218
219
|
prerelease: false
|
|
219
220
|
version_requirements: !ruby/object:Gem::Requirement
|
|
220
221
|
requirements:
|
|
221
222
|
- - ">="
|
|
222
223
|
- !ruby/object:Gem::Version
|
|
223
|
-
version: 3.
|
|
224
|
+
version: 3.4.2
|
|
224
225
|
description: Patch Retention API wrapper.
|
|
225
226
|
email:
|
|
226
227
|
- webmaster@playbypoint.com
|
|
227
228
|
- g3ortega@gmail.com
|
|
229
|
+
- alvaro.rp1593@gmail.com
|
|
228
230
|
executables: []
|
|
229
231
|
extensions: []
|
|
230
232
|
extra_rdoc_files: []
|