parseapi 0.4.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fae571978d7957f72ae69536a6d4c72e80ba58e7228acb0089e1344e54b8a0cf
4
- data.tar.gz: 41bd5c285c7ec8c138f00d37a1378d61ece08374cc0df6a933ba41c9f457db11
3
+ metadata.gz: 8229ca82d3288ebdae0032fc5d3d8865d12b241f1627b6ccf2409e568eb5501a
4
+ data.tar.gz: 70929f039ede8fa845145a3c3803c186d1a8dfb8dd2af4b45b6fcf058772cb1f
5
5
  SHA512:
6
- metadata.gz: 394f8262c936d35b38f9947b8a41818bcc29bdb99fb3dfb348830c021f5e3be92ab9556b74262917598ef028d608be498c150f8574c2f8a266f6281d09d1240d
7
- data.tar.gz: 01d9c5a27c4a415f061ce707992a5b277fe522e6b0fb01eda56aa6910d728908dc4f3cfa209cad20f30c174714c5619acac38202f6022a13793d210921cab2f1
6
+ metadata.gz: 0b22da2a9cec679abc8ed1a8a60dcd2365cdb2776c49c58089df907653fd6971198d317348f72d4a5b8cf8d0c7ae8c8f51db34516aa3817cfe99df4fe830b983
7
+ data.tar.gz: 79894060499900eb0a2210fd36b260b68bba1b837a537274efe81e4aa0cc1353a4f29e89b19429486242b71993b3eb014c6109bd64a5caf2b4b6a1f21fbda87f
data/README.md CHANGED
@@ -13,11 +13,13 @@ Get a key at [parseapi.com](https://parseapi.com). The client also reads `PARSEA
13
13
 
14
14
  ## API versions
15
15
 
16
- Choose your team's API version in [Dashboard → API version](https://parseapi.com/dashboard/versions). One setting applies to every key, including new and replacement keys. Existing teams keep `1.0.0`; new teams start on `2.0.0`. Keep the same keys and lookup URLs. Installing or upgrading the package does not change the team's setting.
16
+ Version 1.0.0 explicitly selects the API contract supported by this SDK. It sends `Parse-Version: 2.0.0` on every lookup so responses match the API contract supported by the package. Your key and the team's saved default stay the same.
17
17
 
18
- Published SDK `0.3.2` matches API `1.0.0`. The examples and response types in this source tree target API `2.0.0`, including changes that are not in `0.3.2`. Use a package release documented for your team's version. These types do not model every historical response; moving to `2.0.0` may require updating code that reads renamed, moved or removed fields.
18
+ Upgrade the dependency in staging, review the [release notes](https://parseapi.com/docs/releases), and test the application before deploying the same code and dependency version to production. Commit your dependency lockfile so the tested package travels with your deployment. Future major SDK upgrades can select a newer API contract.
19
19
 
20
- Test the target contract in a separate development team before changing your production team's version. A change applies to every integration in that team. See [API versions and migration](https://parseapi.com/docs/versioning).
20
+ Previously published SDKs keep their existing behavior and use the team's default. Requests without `Parse-Version` also use that default, managed in [Dashboard API version](https://parseapi.com/dashboard/versions). Keep it unchanged while older applications depend on it. Rolling back to an SDK without a version header restores the team default, so rollback only restores the old contract when that default has stayed unchanged.
21
+
22
+ The package owns its supported API version. For direct HTTP integrations, an explicit `Parse-Version` header selects a supported contract. See [API versions and migration](https://parseapi.com/docs/versioning).
21
23
 
22
24
  ## Weather from a postal code
23
25
 
@@ -85,6 +87,7 @@ parse.currency_rate('USD', 'EUR')
85
87
  parse.language('en')
86
88
  parse.name('BILLY OSHALL')
87
89
  parse.name('Andrea', country: 'IT', deep: true)
90
+ parse.name('Robert James Smith', deep: true, name_locale: 'en')
88
91
  parse.time # UTC now
89
92
  parse.time('America/New_York')
90
93
  parse.time('America/New_York', at: '2026-09-05T15:00', to: 'Europe/London')
@@ -119,6 +122,20 @@ Each lookup returns a plain hash with string keys. Related lookups are separate
119
122
 
120
123
  DNS uses pooled requests on every plan. Omit `type` to check A, AAAA, CNAME, MX, NS, TXT, SOA, CAA, SRV and PTR. Records contain `name`, `type`, `ttl` in seconds and a DNS presentation `value`. TXT values retain quoting and chunk boundaries. A selected question can include its CNAME chain. Empty records mean no records. Lookup failures remain errors.
121
124
 
125
+ Name paid deep includes flat `short`, `directory`, and `initials` fields beside `gender` and `salutation`. `name_locale` selects CLDR formatting rules and defaults to `en`. It changes formatting only. Country remains gender context, and unavailable formatting is null. Older responses may omit these fields.
126
+
127
+ ## Display language
128
+
129
+ Choose display names for one request:
130
+
131
+ ```ruby
132
+ parse.country('DE', lang: 'fr')
133
+ ```
134
+
135
+ `lang` is optional on geography lookups and their lists/searches, Currency lookup, Language, Date, Time/Timezone, Emoji lookup/search, and unit discovery. IP, ASN, Company and NPI also accept it for their geographic labels. Codes, native names, quantities and response structure retain their meanings. Source coverage determines which labels are translated; unavailable labels use the API's documented fallback.
136
+
137
+ The next call keeps its usual default unless it also supplies `lang`. Existing `deep` rules still apply. Date `format` and measurement `locale` remain explicit input-parsing controls.
138
+
122
139
  ## Time
123
140
 
124
141
  `time` returns local ISO `at` with its UTC offset and integer Unix seconds in `unix`. The core `offset` preserves exact precision. Optional `deep.offset_seconds` gives the numeric offset, while `deep.offset_minutes` gives whole minutes. Historical offsets and ISO times can include offset seconds. Omitted `at` means now. With `to`, an offsetless `at` is source wall time. Otherwise it is UTC. Include an offset for repeated local times around a clock change. Current time and conversion use pooled requests on every plan. Coordinate clock fields can be null when the timezone is unknown. Existing `timezone` methods remain supported.
@@ -143,7 +160,9 @@ place = parse.postal('28202', country: 'US', deep: true)
143
160
  property_tax = place.dig('deep', 'property_tax')
144
161
  ```
145
162
 
146
- Read `population_period` alongside `population`: a reporting year (`YYYY`) or period (`YYYY-YYYY`), null when unknown or unverifiable. Keep missing or null values unknown and preserve a known zero. These fields belong to full place profiles. State district lists include each district's population and period. Postal nearby and distance detail remains metropolitan associations only. Continent population and its period remain in core.
163
+ Read `population_period` alongside `population`: a reporting year (`YYYY`) or period (`YYYY-YYYY`), null when unknown or unverifiable. Keep missing or null values unknown and preserve a known zero. These fields belong to full place profiles. State district lists include each district's population and period. Postal nearby and distance detail remains metropolitan associations only. Continent population stays in core.
164
+
165
+ Country deep includes `land_area` and `water_area` in km2, `coastline` in km, and mean `elevation` in metres. `lowest_point` and `highest_point` contain a nullable `name` and an `elevation` in metres. Values below sea level are negative. Missing or null values stay unknown, and zero stays zero.
147
166
 
148
167
  Point returns the timezone ID with the core location. Its optional deep detail adds terrain and compact nearest-city context on every plan. A nearest city is null when none is within 200 km.
149
168
 
@@ -18,6 +18,8 @@ module ParseAPI
18
18
  end
19
19
 
20
20
  class Client
21
+ API_VERSION = '2.0.0'.freeze
22
+ private_constant :API_VERSION
21
23
  DEFAULT_BASE_URL = 'https://api.parseapi.com'.freeze
22
24
  DEFAULT_TIMEOUT = 10
23
25
  DEFAULT_RETRIES = 2
@@ -57,83 +59,83 @@ module ParseAPI
57
59
 
58
60
 
59
61
  # Look up an IP. Deep enrichment is included with a paid plan, without a separate check meter.
60
- def ip(ip, deep: false)
61
- get("/ip/#{seg(ip)}", deep: deep)
62
+ def ip(ip, deep: false, lang: nil)
63
+ get("/ip/#{seg(ip)}", deep: deep, lang: lang)
62
64
  end
63
65
 
64
66
  # Look up the public IP making this request. On a server, this is the server's IP.
65
- def ip_self(deep: false)
66
- get('/ip', deep: deep)
67
+ def ip_self(deep: false, lang: nil)
68
+ get('/ip', deep: deep, lang: lang)
67
69
  end
68
70
 
69
- def continent(code)
70
- get("/continent/#{seg(code)}")
71
+ def continent(code, lang: nil)
72
+ get("/continent/#{seg(code)}", lang: lang)
71
73
  end
72
74
 
73
- def continent_countries(code)
74
- get("/continent/#{seg(code)}/countries")
75
+ def continent_countries(code, lang: nil)
76
+ get("/continent/#{seg(code)}/countries", lang: lang)
75
77
  end
76
78
 
77
79
  def bloc(code)
78
80
  get("/bloc/#{seg(code)}")
79
81
  end
80
82
 
81
- def bloc_countries(code)
82
- get("/bloc/#{seg(code)}/countries")
83
+ def bloc_countries(code, lang: nil)
84
+ get("/bloc/#{seg(code)}/countries", lang: lang)
83
85
  end
84
86
 
85
- def country(code, deep: false)
86
- get("/country/#{seg(code)}", deep: deep)
87
+ def country(code, deep: false, lang: nil)
88
+ get("/country/#{seg(code)}", deep: deep, lang: lang)
87
89
  end
88
90
 
89
- def country_states(code)
90
- get("/country/#{seg(code)}/states")
91
+ def country_states(code, lang: nil)
92
+ get("/country/#{seg(code)}/states", lang: lang)
91
93
  end
92
94
 
93
- def state(code, country: nil, deep: false)
94
- get("/state/#{seg(code)}", country: country, deep: deep)
95
+ def state(code, country: nil, deep: false, lang: nil)
96
+ get("/state/#{seg(code)}", country: country, deep: deep, lang: lang)
95
97
  end
96
98
 
97
- def state_districts(code, country: nil, deep: false)
98
- get("/state/#{seg(code)}/districts", country: country, deep: deep)
99
+ def state_districts(code, country: nil, deep: false, lang: nil)
100
+ get("/state/#{seg(code)}/districts", country: country, deep: deep, lang: lang)
99
101
  end
100
102
 
101
- def district(code, country: nil, state: nil, deep: false)
102
- get("/district/#{seg(code)}", country: country, state: state, deep: deep)
103
+ def district(code, country: nil, state: nil, deep: false, lang: nil)
104
+ get("/district/#{seg(code)}", country: country, state: state, deep: deep, lang: lang)
103
105
  end
104
106
 
105
- def city(name, country: nil, state: nil, deep: false)
106
- get("/city/#{seg(name)}", country: country, state: state, deep: deep)
107
+ def city(name, country: nil, state: nil, deep: false, lang: nil)
108
+ get("/city/#{seg(name)}", country: country, state: state, deep: deep, lang: lang)
107
109
  end
108
110
 
109
- def city_id(id, deep: false)
110
- get("/city/id/#{seg(id)}", deep: deep)
111
+ def city_id(id, deep: false, lang: nil)
112
+ get("/city/id/#{seg(id)}", deep: deep, lang: lang)
111
113
  end
112
114
 
113
- def city_search(query, country: nil, state: nil, limit: nil, deep: false)
114
- get('/city', q: query, country: country, state: state, limit: limit, deep: deep)
115
+ def city_search(query, country: nil, state: nil, limit: nil, deep: false, lang: nil)
116
+ get('/city', q: query, country: country, state: state, limit: limit, deep: deep, lang: lang)
115
117
  end
116
118
 
117
- def city_nearest(lat, lon, deep: false)
118
- get('/city', lat: lat, lon: lon, deep: deep)
119
+ def city_nearest(lat, lon, deep: false, lang: nil)
120
+ get('/city', lat: lat, lon: lon, deep: deep, lang: lang)
119
121
  end
120
122
 
121
- def city_nearby(name, radius: nil, unit: nil, country: nil, state: nil, limit: nil, deep: false)
122
- get("/city/#{seg(name)}/nearby", radius: radius, unit: unit, country: country, state: state, limit: limit, deep: deep)
123
+ def city_nearby(name, radius: nil, unit: nil, country: nil, state: nil, limit: nil, deep: false, lang: nil)
124
+ get("/city/#{seg(name)}/nearby", radius: radius, unit: unit, country: country, state: state, limit: limit, deep: deep, lang: lang)
123
125
  end
124
126
 
125
127
  # Look up a postal area. Pass country when known. Check nullable coordinates before another
126
128
  # location lookup.
127
- def postal(code, country: nil, deep: false)
128
- get("/postal/#{seg(code)}", country: country, deep: deep)
129
+ def postal(code, country: nil, deep: false, lang: nil)
130
+ get("/postal/#{seg(code)}", country: country, deep: deep, lang: lang)
129
131
  end
130
132
 
131
- def postal_nearby(code, country: nil, radius: nil, unit: nil, deep: false)
132
- get("/postal/#{seg(code)}/nearby", country: country, radius: radius, unit: unit, deep: deep)
133
+ def postal_nearby(code, country: nil, radius: nil, unit: nil, deep: false, lang: nil)
134
+ get("/postal/#{seg(code)}/nearby", country: country, radius: radius, unit: unit, deep: deep, lang: lang)
133
135
  end
134
136
 
135
- def postal_distance(from, to, country: nil, deep: false)
136
- get("/postal/#{seg(from)}/distance/#{seg(to)}", country: country, deep: deep)
137
+ def postal_distance(from, to, country: nil, deep: false, lang: nil)
138
+ get("/postal/#{seg(from)}/distance/#{seg(to)}", country: country, deep: deep, lang: lang)
137
139
  end
138
140
 
139
141
  def address(address, country: nil, deep: false)
@@ -148,8 +150,8 @@ module ParseAPI
148
150
  get('/address', q: query, country: country, postal: postal, city: city, state: state, ip: ip)
149
151
  end
150
152
 
151
- def company(number, country: nil, deep: false)
152
- get("/company/#{seg(number)}", country: country, deep: deep)
153
+ def company(number, country: nil, deep: false, lang: nil)
154
+ get("/company/#{seg(number)}", country: country, deep: deep, lang: lang)
153
155
  end
154
156
 
155
157
  # Parse an email and check its format and domain. Deep explicitly requests a metered
@@ -176,8 +178,8 @@ module ParseAPI
176
178
  end
177
179
 
178
180
 
179
- def npi(npi, deep: false)
180
- get("/npi/#{seg(npi)}", deep: deep)
181
+ def npi(npi, deep: false, lang: nil)
182
+ get("/npi/#{seg(npi)}", deep: deep, lang: lang)
181
183
  end
182
184
 
183
185
  # Parse a phone number and its formats. Pass country for national numbers when needed. Deep
@@ -208,8 +210,8 @@ module ParseAPI
208
210
  get("/domain/#{seg(domain)}", deep: deep)
209
211
  end
210
212
 
211
- def asn(asn)
212
- get("/asn/#{seg(asn)}")
213
+ def asn(asn, lang: nil)
214
+ get("/asn/#{seg(asn)}", lang: lang)
213
215
  end
214
216
 
215
217
  def mac(mac)
@@ -256,45 +258,46 @@ module ParseAPI
256
258
  get('/tariff', q: query)
257
259
  end
258
260
 
259
- def currency(code, deep: false)
260
- get("/currency/#{seg(code)}", deep: deep)
261
+ def currency(code, deep: false, lang: nil)
262
+ get("/currency/#{seg(code)}", deep: deep, lang: lang)
261
263
  end
262
264
 
263
265
  def currency_rate(base, quote, date: nil, amount: nil)
264
266
  get("/currency/#{seg(base)}/#{seg(quote)}", date: date, amount: amount)
265
267
  end
266
268
 
267
- def language(code, deep: false)
268
- get("/language/#{seg(code)}", deep: deep)
269
+ def language(code, deep: false, lang: nil)
270
+ get("/language/#{seg(code)}", deep: deep, lang: lang)
269
271
  end
270
272
 
271
- def name(name, country: nil, deep: false)
272
- get("/name/#{seg(name)}", country: country, deep: deep)
273
+ # Name locale selects CLDR formatting, default en, without changing parsing or gender context.
274
+ def name(name, country: nil, deep: false, name_locale: nil)
275
+ get("/name/#{seg(name)}", country: country, deep: deep, name_locale: name_locale)
273
276
  end
274
277
 
275
278
  # Current local time, UTC by default. With to, offsetless at is source wall time.
276
- def time(timezone = nil, at: nil, to: nil, deep: false)
277
- get(timezone.nil? ? '/time' : "/time/#{seg(timezone)}", at: at, to: to, deep: deep)
279
+ def time(timezone = nil, at: nil, to: nil, deep: false, lang: nil)
280
+ get(timezone.nil? ? '/time' : "/time/#{seg(timezone)}", at: at, to: to, deep: deep, lang: lang)
278
281
  end
279
282
 
280
- def time_at(lat, lon, at: nil, to: nil, deep: false)
281
- get('/time', lat: lat, lon: lon, at: at, to: to, deep: deep)
283
+ def time_at(lat, lon, at: nil, to: nil, deep: false, lang: nil)
284
+ get('/time', lat: lat, lon: lon, at: at, to: to, deep: deep, lang: lang)
282
285
  end
283
286
 
284
- def timezone(id, at: nil, to: nil, deep: false)
285
- get("/timezone/#{seg(id)}", at: at, to: to, deep: deep)
287
+ def timezone(id, at: nil, to: nil, deep: false, lang: nil)
288
+ get("/timezone/#{seg(id)}", at: at, to: to, deep: deep, lang: lang)
286
289
  end
287
290
 
288
- def timezone_at(lat, lon, at: nil, deep: false)
289
- get('/timezone', lat: lat, lon: lon, at: at, deep: deep)
291
+ def timezone_at(lat, lon, at: nil, deep: false, lang: nil)
292
+ get('/timezone', lat: lat, lon: lon, at: at, deep: deep, lang: lang)
290
293
  end
291
294
 
292
- def date(date, format: nil, to: nil, deep: false)
293
- get("/date/#{seg(date)}", format: format, to: to, deep: deep)
295
+ def date(date, format: nil, to: nil, deep: false, lang: nil)
296
+ get("/date/#{seg(date)}", format: format, to: to, deep: deep, lang: lang)
294
297
  end
295
298
 
296
- def date_today(to: nil, deep: false)
297
- get('/date', to: to, deep: deep)
299
+ def date_today(to: nil, deep: false, lang: nil)
300
+ get('/date', to: to, deep: deep, lang: lang)
298
301
  end
299
302
 
300
303
  def holiday(country, year: nil)
@@ -312,8 +315,8 @@ module ParseAPI
312
315
  # Resolve the country, state, district and timezone at coordinates. Deep adds terrain and
313
316
  # compact nearest-city context on every plan. The timezone ID stays in core. The nearest city is
314
317
  # null when none is within 200 km.
315
- def point(lat, lon, deep: false)
316
- get('/point', lat: lat, lon: lon, deep: deep)
318
+ def point(lat, lon, deep: false, lang: nil)
319
+ get('/point', lat: lat, lon: lon, deep: deep, lang: lang)
317
320
  end
318
321
 
319
322
  # Get current conditions in metric and imperial units. Paid deep adds specialist current
@@ -323,12 +326,12 @@ module ParseAPI
323
326
  get('/weather', lat: lat, lon: lon, deep: deep, date: date)
324
327
  end
325
328
 
326
- def emoji(emoji, deep: false)
327
- get("/emoji/#{seg(emoji)}", deep: deep)
329
+ def emoji(emoji, deep: false, lang: nil)
330
+ get("/emoji/#{seg(emoji)}", deep: deep, lang: lang)
328
331
  end
329
332
 
330
- def emoji_search(query, limit: nil, deep: false)
331
- get('/emoji', q: query, limit: limit, deep: deep)
333
+ def emoji_search(query, limit: nil, deep: false, lang: nil)
334
+ get('/emoji', q: query, limit: limit, deep: deep, lang: lang)
332
335
  end
333
336
 
334
337
  # Parse or convert a measurement. Amount is a decimal string. Without to, use the
@@ -338,8 +341,8 @@ module ParseAPI
338
341
  end
339
342
 
340
343
  # Discover reviewed units. unit filters compatible conversion targets.
341
- def measure_units(query: nil, type: nil, unit: nil)
342
- get('/measure/units', q: query, type: type, unit: unit)
344
+ def measure_units(query: nil, type: nil, unit: nil, lang: nil)
345
+ get('/measure/units', q: query, type: type, unit: unit, lang: lang)
343
346
  end
344
347
 
345
348
  private
@@ -380,7 +383,7 @@ module ParseAPI
380
383
  end
381
384
 
382
385
  def request_headers(extra)
383
- { 'X-API-Key' => @api_key, 'User-Agent' => "parseapi-ruby/#{VERSION}" }.merge(extra)
386
+ { 'X-API-Key' => @api_key, 'User-Agent' => "parseapi-ruby/#{VERSION}" }.merge(extra).merge('Parse-Version' => API_VERSION)
384
387
  end
385
388
 
386
389
  # Returns [status, headers_hash, body_string]. Overridden in tests.
@@ -1,3 +1,3 @@
1
1
  module ParseAPI
2
- VERSION = '0.4.0'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parseapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ParseAPI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-10 00:00:00.000000000 Z
11
+ date: 2026-09-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: