vatsense 0.1.0 → 0.1.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 +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +125 -155
- data/lib/vatsense/internal/util.rb +19 -6
- data/lib/vatsense/version.rb +1 -1
- data/rbi/vatsense/internal/util.rbi +8 -0
- data/sig/vatsense/internal/util.rbs +4 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a6cbb8615a5f3366f1abe2d7ccd2c4eae2dbcc4ef9b85f72f2ea990e9aafd3d5
|
|
4
|
+
data.tar.gz: 97a498b7db5317fda34e1e4bcd508fc85a0654a1b64f4b1eac5d777b0cb2ab54
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4ad0aaec6739477762e8d267919cf07fd3c863577c2394d982d99805804e7231fc318b09406d2e8cdef0d04c2fc432d14d0ab31bd7f267d15b6ae6f7318c7af2
|
|
7
|
+
data.tar.gz: 510b64b88384f3440a3f811588f428f0f8cb808c284ce4f2e419cad596d73a007e733984aa3ac1cd0db659870b96af0a51e967e192bddcf6e80b3c55870c70d4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1 (2026-04-01)
|
|
4
|
+
|
|
5
|
+
Full Changelog: [v0.1.0...v0.1.1](https://github.com/VAT-Sense/vatsense-ruby/compare/v0.1.0...v0.1.1)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* align path encoding with RFC 3986 section 3.3 ([876d20f](https://github.com/VAT-Sense/vatsense-ruby/commit/876d20f7d38dea0d3e1ce1d9320b583833576b84))
|
|
10
|
+
* **internal:** correct multipart form field name encoding ([96c7cdd](https://github.com/VAT-Sense/vatsense-ruby/commit/96c7cdd5632efd1eb3904179312b2d21ac476439))
|
|
11
|
+
* variable name typo ([6328709](https://github.com/VAT-Sense/vatsense-ruby/commit/63287096c06e8cb992946441e932177c07f2f456))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Chores
|
|
15
|
+
|
|
16
|
+
* **ci:** skip lint on metadata-only changes ([e4e8c73](https://github.com/VAT-Sense/vatsense-ruby/commit/e4e8c73343b5045afbe01653e23301d9a43d194c))
|
|
17
|
+
* **ci:** support opting out of skipping builds on metadata-only commits ([9db0960](https://github.com/VAT-Sense/vatsense-ruby/commit/9db09605215e8727e05cffeea18b91005424b590))
|
|
18
|
+
* **internal:** update gitignore ([6122de9](https://github.com/VAT-Sense/vatsense-ruby/commit/6122de9f488047ff89c3df016886700ed802c335))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Documentation
|
|
22
|
+
|
|
23
|
+
* **readme:** tailor README to VAT Sense use cases ([2b4823e](https://github.com/VAT-Sense/vatsense-ruby/commit/2b4823e2c9bc31eae4c073461defa8b2029f9be0))
|
|
24
|
+
|
|
3
25
|
## 0.1.0 (2026-03-18)
|
|
4
26
|
|
|
5
27
|
Full Changelog: [v0.0.1...v0.1.0](https://github.com/VAT-Sense/vatsense-ruby/compare/v0.0.1...v0.1.0)
|
data/README.md
CHANGED
|
@@ -1,234 +1,204 @@
|
|
|
1
|
-
#
|
|
1
|
+
# VAT Sense Ruby SDK
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
|
|
5
|
-
It is generated with [Stainless](https://www.stainless.com/).
|
|
6
|
-
|
|
7
|
-
## Documentation
|
|
8
|
-
|
|
9
|
-
Documentation for releases of this gem can be found [on RubyDoc](https://gemdocs.org/gems/vatsense).
|
|
10
|
-
|
|
11
|
-
The REST API documentation can be found on [vatsense.com](https://vatsense.com).
|
|
3
|
+
The official Ruby library for the [VAT Sense](https://vatsense.com) REST API. Validate VAT/EORI numbers, look up VAT/GST rates, calculate prices, convert currencies, and generate VAT-compliant invoices.
|
|
12
4
|
|
|
13
5
|
## Installation
|
|
14
6
|
|
|
15
|
-
|
|
7
|
+
```sh
|
|
8
|
+
gem install vatsense
|
|
9
|
+
```
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
Or add to your Gemfile:
|
|
18
12
|
|
|
19
13
|
```ruby
|
|
20
|
-
gem "vatsense"
|
|
14
|
+
gem "vatsense"
|
|
21
15
|
```
|
|
22
16
|
|
|
23
|
-
|
|
17
|
+
Requires Ruby 3.2.0+.
|
|
24
18
|
|
|
25
|
-
##
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
Create a client using your API key from the [VAT Sense dashboard](https://vatsense.com/dashboard). The API uses HTTP Basic Auth with `user` as the username and your API key as the password.
|
|
26
22
|
|
|
27
23
|
```ruby
|
|
28
|
-
require "bundler/setup"
|
|
29
24
|
require "vatsense"
|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
username:
|
|
33
|
-
password:
|
|
26
|
+
client = Vatsense::Client.new(
|
|
27
|
+
username: "user",
|
|
28
|
+
password: "your_api_key",
|
|
34
29
|
)
|
|
35
|
-
|
|
36
|
-
rates = vat_sense.rates.list
|
|
37
|
-
|
|
38
|
-
puts(rates.code)
|
|
39
30
|
```
|
|
40
31
|
|
|
41
|
-
|
|
32
|
+
You can also set the `VAT_SENSE_USERNAME` and `VAT_SENSE_PASSWORD` environment variables and the client will pick them up automatically.
|
|
42
33
|
|
|
43
|
-
|
|
34
|
+
### Validate a VAT number
|
|
44
35
|
|
|
45
36
|
```ruby
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
puts
|
|
50
|
-
puts
|
|
51
|
-
|
|
52
|
-
puts("A 429 status code was received; we should back off a bit.")
|
|
53
|
-
rescue Vatsense::Errors::APIStatusError => e
|
|
54
|
-
puts("Another non-200-range status code was received")
|
|
55
|
-
puts(e.status)
|
|
37
|
+
response = client.validate.check(vat_number: "GB288305674")
|
|
38
|
+
|
|
39
|
+
if response.data.valid
|
|
40
|
+
puts response.data.company.company_name # "BRITISH BROADCASTING CORPORATION"
|
|
41
|
+
puts response.data.company.company_address
|
|
42
|
+
puts response.data.company.country_code # "GB"
|
|
56
43
|
end
|
|
57
44
|
```
|
|
58
45
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
| Cause | Error Type |
|
|
62
|
-
| ---------------- | -------------------------- |
|
|
63
|
-
| HTTP 400 | `BadRequestError` |
|
|
64
|
-
| HTTP 401 | `AuthenticationError` |
|
|
65
|
-
| HTTP 403 | `PermissionDeniedError` |
|
|
66
|
-
| HTTP 404 | `NotFoundError` |
|
|
67
|
-
| HTTP 409 | `ConflictError` |
|
|
68
|
-
| HTTP 422 | `UnprocessableEntityError` |
|
|
69
|
-
| HTTP 429 | `RateLimitError` |
|
|
70
|
-
| HTTP >= 500 | `InternalServerError` |
|
|
71
|
-
| Other HTTP error | `APIStatusError` |
|
|
72
|
-
| Timeout | `APITimeoutError` |
|
|
73
|
-
| Network error | `APIConnectionError` |
|
|
46
|
+
VAT validation works for the UK, EU, Australia, Norway, Switzerland, South Africa, and Brazil.
|
|
74
47
|
|
|
75
|
-
###
|
|
76
|
-
|
|
77
|
-
Certain errors will be automatically retried 2 times by default, with a short exponential backoff.
|
|
78
|
-
|
|
79
|
-
Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, >=500 Internal errors, and timeouts will all be retried by default.
|
|
80
|
-
|
|
81
|
-
You can use the `max_retries` option to configure or disable this:
|
|
48
|
+
### Validate an EORI number
|
|
82
49
|
|
|
83
50
|
```ruby
|
|
84
|
-
|
|
85
|
-
vat_sense = Vatsense::Client.new(
|
|
86
|
-
max_retries: 0 # default is 2
|
|
87
|
-
)
|
|
51
|
+
response = client.validate.check(eori_number: "GB123456789000")
|
|
88
52
|
|
|
89
|
-
|
|
90
|
-
|
|
53
|
+
if response.data.valid
|
|
54
|
+
puts response.data.company.company_name
|
|
55
|
+
end
|
|
91
56
|
```
|
|
92
57
|
|
|
93
|
-
|
|
58
|
+
EORI validation is available for UK and EU numbers only.
|
|
59
|
+
|
|
60
|
+
### Get a consultation number
|
|
94
61
|
|
|
95
|
-
|
|
62
|
+
If you need an official consultation number from VIES (EU) or HMRC (UK), provide your own VAT number as the requester:
|
|
96
63
|
|
|
97
64
|
```ruby
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
65
|
+
response = client.validate.check(
|
|
66
|
+
vat_number: "FR12345678901",
|
|
67
|
+
requester_vat_number: "FR98765432101",
|
|
101
68
|
)
|
|
102
69
|
|
|
103
|
-
|
|
104
|
-
vat_sense.rates.list(request_options: {timeout: 5})
|
|
70
|
+
puts response.data.consultation_number
|
|
105
71
|
```
|
|
106
72
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
Note that requests that time out are retried by default.
|
|
73
|
+
> **Note:** GB requester numbers only work for GB validations, and EU requester numbers only work for EU validations. Cross-region requests are not supported.
|
|
110
74
|
|
|
111
|
-
|
|
75
|
+
### Find the VAT rate for a country
|
|
112
76
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
All parameter and response objects inherit from `Vatsense::Internal::Type::BaseModel`, which provides several conveniences, including:
|
|
116
|
-
|
|
117
|
-
1. All fields, including unknown ones, are accessible with `obj[:prop]` syntax, and can be destructured with `obj => {prop: prop}` or pattern-matching syntax.
|
|
118
|
-
|
|
119
|
-
2. Structural equivalence for equality; if two API calls return the same values, comparing the responses with == will return true.
|
|
77
|
+
```ruby
|
|
78
|
+
rate = client.rates.find(country_code: "DE")
|
|
120
79
|
|
|
121
|
-
|
|
80
|
+
puts rate.data.country_name # "Germany"
|
|
81
|
+
puts rate.data.tax_rate.rate # 19.0
|
|
82
|
+
puts rate.data.tax_rate.class_ # "standard"
|
|
83
|
+
```
|
|
122
84
|
|
|
123
|
-
|
|
85
|
+
### Find a rate for a specific product type
|
|
124
86
|
|
|
125
|
-
|
|
87
|
+
```ruby
|
|
88
|
+
rate = client.rates.find(country_code: "DE", type: "ebooks")
|
|
126
89
|
|
|
127
|
-
|
|
90
|
+
puts rate.data.tax_rate.rate # 7.0
|
|
91
|
+
puts rate.data.tax_rate.class_ # "reduced"
|
|
92
|
+
```
|
|
128
93
|
|
|
129
|
-
|
|
94
|
+
### Find a rate by IP address
|
|
130
95
|
|
|
131
|
-
|
|
96
|
+
Useful for determining the correct rate based on your customer's location:
|
|
132
97
|
|
|
133
98
|
```ruby
|
|
134
|
-
rates
|
|
135
|
-
vat_sense.rates.list(
|
|
136
|
-
request_options: {
|
|
137
|
-
extra_query: {my_query_parameter: value},
|
|
138
|
-
extra_body: {my_body_parameter: value},
|
|
139
|
-
extra_headers: {"my-header": value}
|
|
140
|
-
}
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
puts(rates[:my_undocumented_property])
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
#### Undocumented request params
|
|
99
|
+
rate = client.rates.find(ip_address: "185.86.151.11")
|
|
147
100
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
101
|
+
puts rate.data.country_code # "GB"
|
|
102
|
+
puts rate.data.tax_rate.rate # 20.0
|
|
103
|
+
```
|
|
151
104
|
|
|
152
|
-
|
|
105
|
+
### Calculate a VAT-inclusive price
|
|
153
106
|
|
|
154
107
|
```ruby
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
headers: {"useful-header": "interesting-value"},
|
|
160
|
-
body: {"hello": "world"}
|
|
108
|
+
result = client.rates.calculate_price(
|
|
109
|
+
price: "100.00",
|
|
110
|
+
tax_type: "excl",
|
|
111
|
+
country_code: "FR",
|
|
161
112
|
)
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Concurrency & connection pooling
|
|
165
|
-
|
|
166
|
-
The `Vatsense::Client` instances are threadsafe, but are only are fork-safe when there are no in-flight HTTP requests.
|
|
167
|
-
|
|
168
|
-
Each instance of `Vatsense::Client` has its own HTTP connection pool with a default size of 99. As such, we recommend instantiating the client once per application in most settings.
|
|
169
113
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
114
|
+
puts result.data.vat_price.price_incl_vat # Price including VAT
|
|
115
|
+
puts result.data.vat_price.price_excl_vat # Price excluding VAT
|
|
116
|
+
puts result.data.vat_price.vat_rate # VAT rate applied
|
|
117
|
+
puts result.data.vat_price.vat # VAT amount
|
|
118
|
+
```
|
|
173
119
|
|
|
174
|
-
|
|
120
|
+
### List all VAT rates
|
|
175
121
|
|
|
176
|
-
|
|
122
|
+
```ruby
|
|
123
|
+
rates = client.rates.list
|
|
177
124
|
|
|
178
|
-
|
|
125
|
+
rates.data.each do |rate|
|
|
126
|
+
puts "#{rate.country_code}: #{rate.country_name}"
|
|
127
|
+
end
|
|
179
128
|
|
|
180
|
-
|
|
181
|
-
|
|
129
|
+
# Filter to EU countries only
|
|
130
|
+
eu_rates = client.rates.list(eu: true)
|
|
182
131
|
```
|
|
183
132
|
|
|
184
|
-
|
|
133
|
+
## Handling errors
|
|
185
134
|
|
|
186
|
-
|
|
187
|
-
# Hashes work, but are not typesafe:
|
|
188
|
-
vat_sense.rates.list
|
|
135
|
+
When the API returns an error, the library raises a typed exception:
|
|
189
136
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
137
|
+
```ruby
|
|
138
|
+
begin
|
|
139
|
+
response = client.validate.check(vat_number: "GB288305674")
|
|
140
|
+
rescue Vatsense::Errors::APIConnectionError => e
|
|
141
|
+
# Network issue, could not reach the API
|
|
142
|
+
puts e.message
|
|
143
|
+
rescue Vatsense::Errors::RateLimitError => e
|
|
144
|
+
# 429: Too many requests (300/min general limit, 3/sec for UK validation)
|
|
145
|
+
puts "Rate limited, try again shortly"
|
|
146
|
+
rescue Vatsense::Errors::APIStatusError => e
|
|
147
|
+
# Covers all other HTTP errors
|
|
148
|
+
puts e.status
|
|
149
|
+
puts e.message
|
|
150
|
+
end
|
|
193
151
|
```
|
|
194
152
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
Since this library does not depend on `sorbet-runtime`, it cannot provide [`T::Enum`](https://sorbet.org/docs/tenum) instances. Instead, we provide "tagged symbols" instead, which is always a primitive at runtime:
|
|
153
|
+
A `412` error means the upstream validation service (VIES, HMRC, etc.) is temporarily unavailable. These requests do not count against your usage quota.
|
|
198
154
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
155
|
+
| Status Code | Error Type |
|
|
156
|
+
| ----------- | ------------------------------------------- |
|
|
157
|
+
| 400 | `Vatsense::Errors::BadRequestError` |
|
|
158
|
+
| 401 | `Vatsense::Errors::AuthenticationError` |
|
|
159
|
+
| 404 | `Vatsense::Errors::NotFoundError` |
|
|
160
|
+
| 409 | `Vatsense::Errors::ConflictError` |
|
|
161
|
+
| 429 | `Vatsense::Errors::RateLimitError` |
|
|
162
|
+
| >= 500 | `Vatsense::Errors::InternalServerError` |
|
|
163
|
+
| N/A | `Vatsense::Errors::APIConnectionError` |
|
|
202
164
|
|
|
203
|
-
|
|
204
|
-
T.reveal_type(Vatsense::RateCalculatePriceParams::TaxType::INCL)
|
|
205
|
-
```
|
|
165
|
+
## Retries
|
|
206
166
|
|
|
207
|
-
|
|
167
|
+
Failed requests are automatically retried up to 2 times with exponential backoff. This includes connection errors, timeouts, 429, and 5xx responses.
|
|
208
168
|
|
|
209
169
|
```ruby
|
|
210
|
-
#
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
170
|
+
# Disable retries
|
|
171
|
+
client = Vatsense::Client.new(
|
|
172
|
+
username: "user",
|
|
173
|
+
password: "your_api_key",
|
|
174
|
+
max_retries: 0,
|
|
214
175
|
)
|
|
215
176
|
|
|
216
|
-
#
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
177
|
+
# Or configure per request
|
|
178
|
+
response = client.validate.check(
|
|
179
|
+
vat_number: "GB288305674",
|
|
180
|
+
request_options: { max_retries: 5 },
|
|
220
181
|
)
|
|
221
182
|
```
|
|
222
183
|
|
|
223
|
-
##
|
|
184
|
+
## Available services
|
|
224
185
|
|
|
225
|
-
|
|
186
|
+
| Service | Description |
|
|
187
|
+
| --------------------- | ----------------------------------------------- |
|
|
188
|
+
| `client.validate` | Validate VAT and EORI numbers |
|
|
189
|
+
| `client.rates` | VAT/GST rate lookups, price calculations |
|
|
190
|
+
| `client.countries` | Country data and province lookups |
|
|
191
|
+
| `client.currency` | Exchange rates and currency conversion |
|
|
192
|
+
| `client.invoice` | Create and manage VAT-compliant invoices |
|
|
193
|
+
| `client.usage` | Check your API usage |
|
|
226
194
|
|
|
227
|
-
|
|
195
|
+
## Documentation
|
|
228
196
|
|
|
229
|
-
|
|
197
|
+
Full API documentation is available at [vatsense.com/documentation](https://vatsense.com/documentation).
|
|
230
198
|
|
|
231
|
-
|
|
199
|
+
## Versioning
|
|
200
|
+
|
|
201
|
+
This package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions. As the library is in initial development and has a major version of `0`, APIs may change at any time.
|
|
232
202
|
|
|
233
203
|
## Contributing
|
|
234
204
|
|
|
@@ -157,7 +157,7 @@ module Vatsense
|
|
|
157
157
|
in Hash | nil => coerced
|
|
158
158
|
coerced
|
|
159
159
|
else
|
|
160
|
-
message = "Expected a #{Hash} or #{Vatsense::Internal::Type::BaseModel}, got #{
|
|
160
|
+
message = "Expected a #{Hash} or #{Vatsense::Internal::Type::BaseModel}, got #{input.inspect}"
|
|
161
161
|
raise ArgumentError.new(message)
|
|
162
162
|
end
|
|
163
163
|
end
|
|
@@ -237,6 +237,11 @@ module Vatsense
|
|
|
237
237
|
end
|
|
238
238
|
end
|
|
239
239
|
|
|
240
|
+
# @type [Regexp]
|
|
241
|
+
#
|
|
242
|
+
# https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3
|
|
243
|
+
RFC_3986_NOT_PCHARS = /[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/
|
|
244
|
+
|
|
240
245
|
class << self
|
|
241
246
|
# @api private
|
|
242
247
|
#
|
|
@@ -247,6 +252,15 @@ module Vatsense
|
|
|
247
252
|
"#{uri.scheme}://#{uri.host}#{":#{uri.port}" unless uri.port == uri.default_port}"
|
|
248
253
|
end
|
|
249
254
|
|
|
255
|
+
# @api private
|
|
256
|
+
#
|
|
257
|
+
# @param path [String, Integer]
|
|
258
|
+
#
|
|
259
|
+
# @return [String]
|
|
260
|
+
def encode_path(path)
|
|
261
|
+
path.to_s.gsub(Vatsense::Internal::Util::RFC_3986_NOT_PCHARS) { ERB::Util.url_encode(_1) }
|
|
262
|
+
end
|
|
263
|
+
|
|
250
264
|
# @api private
|
|
251
265
|
#
|
|
252
266
|
# @param path [String, Array<String>]
|
|
@@ -259,7 +273,7 @@ module Vatsense
|
|
|
259
273
|
in []
|
|
260
274
|
""
|
|
261
275
|
in [String => p, *interpolations]
|
|
262
|
-
encoded = interpolations.map {
|
|
276
|
+
encoded = interpolations.map { encode_path(_1) }
|
|
263
277
|
format(p, *encoded)
|
|
264
278
|
end
|
|
265
279
|
end
|
|
@@ -571,16 +585,15 @@ module Vatsense
|
|
|
571
585
|
y << "Content-Disposition: form-data"
|
|
572
586
|
|
|
573
587
|
unless key.nil?
|
|
574
|
-
|
|
575
|
-
y << "; name=\"#{name}\""
|
|
588
|
+
y << "; name=\"#{key}\""
|
|
576
589
|
end
|
|
577
590
|
|
|
578
591
|
case val
|
|
579
592
|
in Vatsense::FilePart unless val.filename.nil?
|
|
580
|
-
filename =
|
|
593
|
+
filename = encode_path(val.filename)
|
|
581
594
|
y << "; filename=\"#{filename}\""
|
|
582
595
|
in Pathname | IO
|
|
583
|
-
filename =
|
|
596
|
+
filename = encode_path(::File.basename(val.to_path))
|
|
584
597
|
y << "; filename=\"#{filename}\""
|
|
585
598
|
else
|
|
586
599
|
end
|
data/lib/vatsense/version.rb
CHANGED
|
@@ -148,12 +148,20 @@ module Vatsense
|
|
|
148
148
|
end
|
|
149
149
|
end
|
|
150
150
|
|
|
151
|
+
# https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3
|
|
152
|
+
RFC_3986_NOT_PCHARS = T.let(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/, Regexp)
|
|
153
|
+
|
|
151
154
|
class << self
|
|
152
155
|
# @api private
|
|
153
156
|
sig { params(uri: URI::Generic).returns(String) }
|
|
154
157
|
def uri_origin(uri)
|
|
155
158
|
end
|
|
156
159
|
|
|
160
|
+
# @api private
|
|
161
|
+
sig { params(path: T.any(String, Integer)).returns(String) }
|
|
162
|
+
def encode_path(path)
|
|
163
|
+
end
|
|
164
|
+
|
|
157
165
|
# @api private
|
|
158
166
|
sig { params(path: T.any(String, T::Array[String])).returns(String) }
|
|
159
167
|
def interpolate_path(path)
|
|
@@ -45,8 +45,12 @@ module Vatsense
|
|
|
45
45
|
-> top?
|
|
46
46
|
} -> top?
|
|
47
47
|
|
|
48
|
+
RFC_3986_NOT_PCHARS: Regexp
|
|
49
|
+
|
|
48
50
|
def self?.uri_origin: (URI::Generic uri) -> String
|
|
49
51
|
|
|
52
|
+
def self?.encode_path: (String | Integer path) -> String
|
|
53
|
+
|
|
50
54
|
def self?.interpolate_path: (String | ::Array[String] path) -> String
|
|
51
55
|
|
|
52
56
|
def self?.decode_query: (String? query) -> ::Hash[String, ::Array[String]]
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: vatsense
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vat Sense
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-04-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: cgi
|