dpd_ie_api 0.2.0 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b91d20b8a6d5d06abf9897fab59bf99ac71490104e2a5dfb730cc32db671fd6
4
- data.tar.gz: ef2e9119ec01c8fcda0e82fb99d03ccd5c340d6ec69a0746a8b659599e7d8848
3
+ metadata.gz: cb11635fe7a354bb8985d5edb82b4e61ae916ed43010849df6add2ef62d6c439
4
+ data.tar.gz: f29f052b67496fd4558640cc53bbaf381ff8e6e8baaaa94cb1bb57079d6d3e96
5
5
  SHA512:
6
- metadata.gz: 6d3683adbfe882a5938337ffaa442c174ddf5089138aeae2107d205acd2aeccd7fd0bd9e9dd3d92757066864faf54a841a2de9728decad57792d9da80a03358f
7
- data.tar.gz: 4edec2a71897a299239641de7b4246d7fd3a1baf3e9fbc2a67bf0a6c3f6e1f7c5a431c01cf538a1139cd8eb040bcfef35c76b599914d8eb4a98aa48b990c7ca6
6
+ metadata.gz: 11361928734bebad3eeb835f74cc7c2c3801010617f417fdb9c7187966ef12d8f25f0072c633ae2edea68580516ae160bc35b128604fba54ede9867819c735b0
7
+ data.tar.gz: 6c2fb2b988f85e0e0cda8fa5f5aa54209c5ad675b863361ccf647538c68571f1e17f6ead4493e8bf870122800dc1d58985293e10fcd4ec98ce6b9ed4e75725ff
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/README.md CHANGED
@@ -1,34 +1,183 @@
1
1
  # DpdIeApi
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
4
-
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/dpd_ie_api`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ A Ruby gem wrapper for the DPD Ireland API.
6
4
 
7
5
  ## Installation
8
6
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
-
11
7
  Install the gem and add to the application's Gemfile by executing:
12
8
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
9
+ ```bash
10
+ bundle add dpd_ie_api
11
+ ```
14
12
 
15
13
  If bundler is not being used to manage dependencies, install the gem by executing:
16
14
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
15
+ ```bash
16
+ gem install dpd_ie_api
17
+ ```
18
+
19
+ ## Design
20
+
21
+ The gem provides a **uniform Ruby interface** across all endpoints. You always work with Ruby hashes and objects — the gem picks the best format (JSON or XML) for each endpoint internally:
22
+
23
+ | Endpoint | Request Format | Response Format |
24
+ |----------|---------------|-----------------|
25
+ | Authorize | JSON | JSON |
26
+ | PreAdvice | XML | XML |
27
+ | Track | XML | JSON |
28
+
29
+ JSON is used wherever the DPD API supports it (simpler, no XML parsing overhead). XML is used only where the API requires it. This is entirely invisible to gem consumers.
18
30
 
19
31
  ## Usage
20
32
 
21
- TODO: Write usage instructions here
33
+ ### Authentication
34
+
35
+ Obtain an access token using your static token and credentials.
36
+
37
+ ```ruby
38
+ auth = DpdIeApi::Auth.fetch_token("YOUR_STATIC_TOKEN", "YOUR_USER", "YOUR_PASSWORD")
39
+ access_token = auth.access_token
40
+ refresh_token = auth.refresh_token
41
+ expires_in = auth.expires_in
42
+ ```
43
+
44
+ > [!IMPORTANT]
45
+ > The access token expires after a certain period (indicated by `expires_in`). It is highly recommended to cache the `access_token` and reuse it until it expires to avoid unnecessary API calls and potential rate limiting.
46
+
47
+ For production, pass `prod: true`:
48
+
49
+ ```ruby
50
+ auth = DpdIeApi::Auth.fetch_token("YOUR_STATIC_TOKEN", "YOUR_USER", "YOUR_PASSWORD", prod: true)
51
+ ```
52
+
53
+ Then, initialize the client with your access token:
54
+
55
+ ```ruby
56
+ client = DpdIeApi::Client.new(
57
+ access_token,
58
+ prod: true # set to true for production, false for pre-production (default)
59
+ )
60
+ ```
61
+
62
+ **Client constructor:**
63
+
64
+ - `access_token` - Bearer token from `DpdIeApi::Auth.fetch_token` (required)
65
+ - `prod:` - Set to `true` for production (`https://papi.dpd.ie`), `false` for pre-production (`https://pre-prod-papi.dpd.ie`). Defaults to `false`.
66
+
67
+ ### Error Handling
68
+
69
+ All endpoints raise `DpdIeApi::Error` on failure. The error object exposes both HTTP status code and response body:
70
+
71
+ ```ruby
72
+ begin
73
+ client.preadvice.create(payload)
74
+ rescue DpdIeApi::Error => error
75
+ puts error.message
76
+ puts error.response_http_code
77
+ puts error.response_body
78
+ end
79
+ ```
80
+
81
+ ### Preadvice
82
+
83
+ #### Create
84
+
85
+ Create a preadvice consignment. Pass a Ruby hash — the gem handles XML serialization internally.
86
+
87
+ ```ruby
88
+ payload = {
89
+ consignment: {
90
+ record_id: '1',
91
+ customer_account: '5993L3',
92
+ total_parcels: '1',
93
+ relabel: '1',
94
+ service_option: '5',
95
+ service_type: '1',
96
+ weight: '5',
97
+ delivery_address: {
98
+ contact: 'Warehouse address',
99
+ contact_telephone: '0877777777',
100
+ contact_email: 'test.email@no-email.gg',
101
+ business_name: 'Shop name',
102
+ address_line1: 'Trimgate St',
103
+ address_line2: 'Athlone Business Park',
104
+ address_line3: 'Navan',
105
+ address_line4: 'Meath',
106
+ post_code: 'N37XK83',
107
+ country_code: 'IE',
108
+ },
109
+ collection_address: {
110
+ contact: 'Customer address',
111
+ contact_telephone: '0877777777',
112
+ contact_email: 'test.email@no-email.gg',
113
+ business_name: 'Customer name',
114
+ address_line1: '40 Drumcondra Rd Lower',
115
+ address_line2: '',
116
+ address_line3: 'Drumcondra',
117
+ address_line4: 'Dublin',
118
+ post_code: 'N37XK83',
119
+ country_code: 'IE'
120
+ },
121
+ references: [
122
+ { reference_name: 'Reference1', reference_value: 'Order Name 123', parcel_number: '1' },
123
+ ]
124
+ }
125
+ }
126
+
127
+ result = client.preadvice.create(payload)
128
+ puts result.status
129
+ puts result.consignment.tracking_number
130
+ puts result.consignment.label_image
131
+ ```
132
+
133
+ > [!NOTE]
134
+ > Hash keys can be symbols (snake_case, auto-converted to PascalCase XML elements) or strings (passed through as-is for exact control). For example, use `"RecordID" => '1'` if the API requires a specific casing that differs from the automatic conversion.
135
+
136
+ ### Track
137
+
138
+ #### Find
139
+
140
+ Retrieve tracking information for a consignment.
141
+
142
+ ```ruby
143
+ tracking = client.track.find("800436802")
144
+
145
+ puts tracking.tracking_number
146
+ puts tracking.consignment_number
147
+ puts tracking.consignment_status
148
+ puts tracking.consignment_service
149
+
150
+ # Tracking history events
151
+ event = tracking.tracking_history.event_detail
152
+ puts event.event_date
153
+ puts event.event_time
154
+ puts event.event_type_name
155
+ puts event.event_depot_name
156
+ ```
157
+
158
+ The `tracking_type` defaults to `"consignment"` but can be overridden:
159
+
160
+ ```ruby
161
+ tracking = client.track.find("800436802", tracking_type: "parcel")
162
+ ```
163
+
164
+ ### Response Objects
165
+
166
+ All endpoints return response objects that provide:
167
+
168
+ - **Dot notation access** — `result.consignment.tracking_number` (keys are auto-underscored)
169
+ - **`#raw`** — the original parsed response hash with original PascalCase keys
170
+ - **`#to_hash`** — convert the response object back to a Ruby hash
22
171
 
23
172
  ## Development
24
173
 
25
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
174
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
26
175
 
27
176
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
177
 
29
178
  ## Contributing
30
179
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/dpd_ie_api. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/dpd_ie_api/blob/main/CODE_OF_CONDUCT.md).
180
+ Bug reports and pull requests are welcome on GitHub at https://github.com/postco/dpd_ie_api. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/postco/dpd_ie_api/blob/main/CODE_OF_CONDUCT.md).
32
181
 
33
182
  ## License
34
183
 
@@ -36,4 +185,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
36
185
 
37
186
  ## Code of Conduct
38
187
 
39
- Everyone interacting in the DpdIeApi project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/dpd_ie_api/blob/main/CODE_OF_CONDUCT.md).
188
+ Everyone interacting in the DpdIeApi project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/postco/dpd_ie_api/blob/main/CODE_OF_CONDUCT.md).
data/Rakefile CHANGED
@@ -1,4 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/gem_tasks'
4
- task default: %i[]
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'json'
5
+
6
+ module DpdIeApi
7
+ class Auth
8
+ PROD_BASE_URL = 'https://papi.dpd.ie'
9
+ TEST_BASE_URL = 'https://pre-prod-papi.dpd.ie'
10
+ AUTH_PATH = '/common/api/authorize'
11
+
12
+ def self.fetch_token(static_token, user, password, prod: false)
13
+ base_url = prod ? PROD_BASE_URL : TEST_BASE_URL
14
+ url = "#{base_url}#{AUTH_PATH}"
15
+
16
+ response = Faraday.post(url) do |req|
17
+ req.headers['Authorization'] = "Basic #{static_token}"
18
+ req.headers['Content-Type'] = 'application/json'
19
+ req.headers['Accept'] = 'application/json'
20
+ req.body = { 'User' => user, 'Password' => password, 'Type' => 'CUST' }.to_json
21
+ end
22
+
23
+ unless response.success?
24
+ raise DpdIeApi::Error.new(
25
+ "Failed to authorize: #{response.status} - #{response.body}",
26
+ response_http_code: response.status,
27
+ response_body: response.body
28
+ )
29
+ end
30
+
31
+ parsed = JSON.parse(response.body)
32
+
33
+ if parsed['Status'] == 'FAIL'
34
+ raise DpdIeApi::Error.new(
35
+ "Authorization error: #{parsed['Reason']}",
36
+ response_http_code: response.status,
37
+ response_body: response.body
38
+ )
39
+ end
40
+
41
+ Objects::Auth.new(parsed)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+
5
+ module DpdIeApi
6
+ class Client
7
+ PROD_BASE_URL = 'https://papi.dpd.ie'
8
+ TEST_BASE_URL = 'https://pre-prod-papi.dpd.ie'
9
+
10
+ def initialize(access_token, prod: false)
11
+ @access_token = access_token
12
+ @prod = prod
13
+ end
14
+
15
+ def base_url
16
+ @prod ? PROD_BASE_URL : TEST_BASE_URL
17
+ end
18
+
19
+ def connection
20
+ @connection ||= Faraday.new(url: base_url) do |f|
21
+ f.headers['Authorization'] = "Bearer #{@access_token}"
22
+ f.headers['Content-Type'] = 'application/xml'
23
+ end
24
+ end
25
+
26
+ def preadvice
27
+ Resources::Preadvice.new(self)
28
+ end
29
+
30
+ def track
31
+ Resources::Track.new(self)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DpdIeApi
4
+ module Objects
5
+ class Auth < Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'active_support/core_ext/string'
5
+ require 'ostruct'
6
+
7
+ module DpdIeApi
8
+ module Objects
9
+ class Base < OpenStruct
10
+ attr_reader :original_response
11
+
12
+ def initialize(attributes)
13
+ @original_response = deep_freeze_object(attributes)
14
+ super(to_ostruct(attributes))
15
+ end
16
+
17
+ def to_ostruct(obj)
18
+ if obj.is_a?(Hash)
19
+ OpenStruct.new(obj.transform_keys { |key| key.to_s.underscore }.transform_values { |val| to_ostruct(val) })
20
+ elsif obj.is_a?(Array)
21
+ obj.map { |o| to_ostruct(o) }
22
+ else
23
+ obj
24
+ end
25
+ end
26
+
27
+ def to_hash
28
+ ostruct_to_hash(self)
29
+ end
30
+
31
+ def raw
32
+ @original_response
33
+ end
34
+
35
+ private
36
+
37
+ def deep_freeze_object(obj)
38
+ case obj
39
+ when Hash
40
+ obj.transform_values { |value| deep_freeze_object(value) }.freeze
41
+ when Array
42
+ obj.map { |item| deep_freeze_object(item) }.freeze
43
+ else
44
+ obj.respond_to?(:freeze) ? obj.freeze : obj
45
+ end
46
+ end
47
+
48
+ def ostruct_to_hash(object)
49
+ case object
50
+ when OpenStruct
51
+ hash = object.to_h.except(:table)
52
+ hash.transform_keys(&:to_s).transform_values { |value| ostruct_to_hash(value) }
53
+ when Array
54
+ object.map { |item| ostruct_to_hash(item) }
55
+ when Hash
56
+ object.transform_keys(&:to_s).transform_values { |value| ostruct_to_hash(value) }
57
+ else
58
+ object
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DpdIeApi
4
+ module Objects
5
+ class Preadvice < Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DpdIeApi
4
+ module Objects
5
+ class Track < Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DpdIeApi
4
+ module Resources
5
+ class Preadvice
6
+ PREADVICE_PATH = '/common/api/preadvice'
7
+
8
+ def initialize(client)
9
+ @client = client
10
+ end
11
+
12
+ def create(payload)
13
+ xml_body = DpdIeApi::XmlBuilder.build('PreAdvice', payload)
14
+
15
+ response = @client.connection.post(PREADVICE_PATH) do |req|
16
+ req.body = xml_body
17
+ end
18
+
19
+ unless response.success?
20
+ raise DpdIeApi::Error.new(
21
+ "Failed to create preadvice: #{response.status} - #{response.body}",
22
+ response_http_code: response.status,
23
+ response_body: response.body
24
+ )
25
+ end
26
+
27
+ parsed = DpdIeApi::XmlParser.parse(response.body, '//PreAdviceResponse')
28
+
29
+ if parsed['Status'] == 'FAIL'
30
+ raise DpdIeApi::Error.new(
31
+ "Preadvice error: #{parsed['PreAdviceErrorDetails']}",
32
+ response_http_code: response.status,
33
+ response_body: response.body
34
+ )
35
+ end
36
+
37
+ Objects::Preadvice.new(parsed)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module DpdIeApi
6
+ module Resources
7
+ class Track
8
+ TRACK_PATH = '/common/api/track'
9
+
10
+ def initialize(client)
11
+ @client = client
12
+ end
13
+
14
+ def find(tracking_number, tracking_type: 'consignment')
15
+ xml_body = build_tracking_xml(tracking_number, tracking_type)
16
+
17
+ response = @client.connection.post(TRACK_PATH) do |req|
18
+ req.headers['Accept'] = 'application/json'
19
+ req.body = xml_body
20
+ end
21
+
22
+ unless response.success?
23
+ raise DpdIeApi::Error.new(
24
+ "Failed to track consignment: #{response.status} - #{response.body}",
25
+ response_http_code: response.status,
26
+ response_body: response.body
27
+ )
28
+ end
29
+
30
+ parsed = JSON.parse(response.body)
31
+
32
+ if parsed['TrackingErrorInfo']
33
+ error_info = unwrap(parsed['TrackingErrorInfo'])
34
+ error_detail = unwrap(error_info['TrackingErrorDetail'])
35
+ raise DpdIeApi::Error.new(
36
+ "Tracking error: #{error_detail['ErrorDetailCodeDesc']}",
37
+ response_http_code: response.status,
38
+ response_body: response.body
39
+ )
40
+ end
41
+
42
+ Objects::Track.new(unwrap(parsed['TrackingInfo']))
43
+ end
44
+
45
+ private
46
+
47
+ def unwrap(value)
48
+ value.is_a?(Array) ? value.first : value
49
+ end
50
+
51
+ def build_tracking_xml(tracking_number, tracking_type)
52
+ DpdIeApi::XmlBuilder.build('TrackingRequest', {
53
+ request_line: {
54
+ tracking_number: tracking_number,
55
+ tracking_type: tracking_type
56
+ }
57
+ })
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DpdIeApi
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.1'
5
5
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+ require 'active_support/core_ext/string/inflections'
5
+
6
+ module DpdIeApi
7
+ class XmlBuilder
8
+ def self.build(root_name, data)
9
+ builder = Nokogiri::XML::Builder.new(encoding: 'iso-8859-1') do |xml|
10
+ xml.send(root_name) do
11
+ hash_to_xml(xml, data)
12
+ end
13
+ end
14
+ builder.to_xml
15
+ end
16
+
17
+ class << self
18
+ private
19
+
20
+ def hash_to_xml(xml, data)
21
+ data.each do |key, value|
22
+ element_name = normalize_key(key)
23
+
24
+ case value
25
+ when Hash
26
+ xml.send(element_name) do
27
+ hash_to_xml(xml, value)
28
+ end
29
+ when Array
30
+ xml.send(element_name) do
31
+ child_name = element_name.singularize
32
+ value.each do |item|
33
+ if item.is_a?(Hash)
34
+ xml.send(child_name) do
35
+ hash_to_xml(xml, item)
36
+ end
37
+ else
38
+ xml.send(child_name, item.to_s)
39
+ end
40
+ end
41
+ end
42
+ else
43
+ xml.send(element_name, value.to_s)
44
+ end
45
+ end
46
+ end
47
+
48
+ def normalize_key(key)
49
+ case key
50
+ when Symbol then key.to_s.camelize
51
+ when String then key
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+
5
+ module DpdIeApi
6
+ class XmlParser
7
+ def self.parse(body, root_xpath)
8
+ doc = Nokogiri::XML(body)
9
+ root = doc.at_xpath(root_xpath)
10
+ xml_node_to_hash(root)
11
+ end
12
+
13
+ class << self
14
+ private
15
+
16
+ def xml_node_to_hash(node)
17
+ return nil if node.nil?
18
+
19
+ children = node.element_children
20
+
21
+ return node.text if children.empty?
22
+
23
+ result = {}
24
+ children.each do |child|
25
+ key = child.name
26
+ if result.key?(key)
27
+ result[key] = [result[key]] unless result[key].is_a?(Array)
28
+ result[key] << xml_node_to_hash(child)
29
+ else
30
+ result[key] = xml_node_to_hash(child)
31
+ end
32
+ end
33
+ result
34
+ end
35
+ end
36
+ end
37
+ end
data/lib/dpd_ie_api.rb CHANGED
@@ -1,8 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "dpd_ie_api/version"
3
+ require_relative 'dpd_ie_api/version'
4
+ require_relative 'dpd_ie_api/objects/base'
5
+ require_relative 'dpd_ie_api/objects/auth'
6
+ require_relative 'dpd_ie_api/objects/preadvice'
7
+ require_relative 'dpd_ie_api/objects/track'
8
+ require_relative 'dpd_ie_api/xml_builder'
9
+ require_relative 'dpd_ie_api/xml_parser'
10
+ require_relative 'dpd_ie_api/auth'
11
+ require_relative 'dpd_ie_api/client'
12
+ require_relative 'dpd_ie_api/resources/preadvice'
13
+ require_relative 'dpd_ie_api/resources/track'
4
14
 
5
15
  module DpdIeApi
6
- class Error < StandardError; end
7
- # Your code goes here...
16
+ class Error < StandardError
17
+ attr_reader :response_http_code, :response_body
18
+
19
+ def initialize(message = nil, response_http_code: nil, response_body: nil)
20
+ @response_http_code = response_http_code
21
+ @response_body = response_body
22
+ super(message)
23
+ end
24
+ end
8
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dpd_ie_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Linh Ho
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: activesupport
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
55
83
  description: Provides a Ruby interface for interacting with the DPD Ireland API, including
56
84
  authorization, label generation, and tracking.
57
85
  email:
@@ -60,22 +88,33 @@ executables: []
60
88
  extensions: []
61
89
  extra_rdoc_files: []
62
90
  files:
91
+ - ".rspec"
63
92
  - CHANGELOG.md
64
93
  - CODE_OF_CONDUCT.md
65
94
  - LICENSE.txt
66
95
  - README.md
67
96
  - Rakefile
68
97
  - lib/dpd_ie_api.rb
98
+ - lib/dpd_ie_api/auth.rb
99
+ - lib/dpd_ie_api/client.rb
100
+ - lib/dpd_ie_api/objects/auth.rb
101
+ - lib/dpd_ie_api/objects/base.rb
102
+ - lib/dpd_ie_api/objects/preadvice.rb
103
+ - lib/dpd_ie_api/objects/track.rb
104
+ - lib/dpd_ie_api/resources/preadvice.rb
105
+ - lib/dpd_ie_api/resources/track.rb
69
106
  - lib/dpd_ie_api/version.rb
107
+ - lib/dpd_ie_api/xml_builder.rb
108
+ - lib/dpd_ie_api/xml_parser.rb
70
109
  - sig/dpd_ie_api.rbs
71
- homepage: https://github.com/hplinh0702/dpd_ie_api
110
+ homepage: https://github.com/postco/dpd_ie_api
72
111
  licenses:
73
112
  - MIT
74
113
  metadata:
75
114
  allowed_push_host: https://rubygems.org
76
- homepage_uri: https://github.com/hplinh0702/dpd_ie_api
77
- source_code_uri: https://github.com/hplinh0702/dpd_ie_api
78
- changelog_uri: https://github.com/hplinh0702/dpd_ie_api/blob/main/CHANGELOG.md
115
+ homepage_uri: https://github.com/postco/dpd_ie_api
116
+ source_code_uri: https://github.com/postco/dpd_ie_api
117
+ changelog_uri: https://github.com/postco/dpd_ie_api/blob/main/CHANGELOG.md
79
118
  post_install_message:
80
119
  rdoc_options: []
81
120
  require_paths: