Skip to content

Commit e094e89

Browse files
authored
Merge pull request #99 from codegress-com/chore/release-1.0.0
chore: release 1.0.0
2 parents f957ac3 + f6f2207 commit e094e89

12 files changed

Lines changed: 97 additions & 74 deletions

File tree

CHANGELOG.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1111

1212
---
1313

14+
## [1.0.0] — 2026-04-23
15+
16+
### Breaking
17+
18+
- `ValueObject` trait split into two traits: `ValueObject` (construction + destructuring) and `PrimitiveValue` (single-primitive accessor via `.value()`). Types backed by a primitive implement both; composite types implement only `ValueObject`.
19+
- Removed the `sql` feature and all SQLx integration. Database mapping is now the responsibility of the application layer (see the ORM guide in `docs/`).
20+
21+
### Added
22+
23+
- `PrimitiveValue` trait with a `.value() -> &Primitive` accessor for types whose canonical form is a single primitive.
24+
- `TryFrom<String>` and `TryFrom<&str>` implemented for all value objects — ergonomic construction without calling `::new()` explicitly.
25+
- Serde deserialization now runs the full validation pipeline; deserializing an invalid value returns an error instead of producing an invalid object.
26+
- Minimum `serde` version pinned to `1.0.116` (required for the `try_from` container attribute).
27+
28+
### Fixed
29+
30+
- Replaced `once_cell::sync::Lazy` with `std::sync::LazyLock` (stable since Rust 1.80); `once_cell` dependency removed.
31+
- Stale `test-sql` CI job removed; `once_cell` removed from the `contact` feature declaration.
32+
33+
---
34+
1435
## [0.1.1] — 2026-04-17
1536

1637
### Added
@@ -39,5 +60,7 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
3960
- `full` meta-feature
4061
- `prelude` module with convenience re-exports
4162

42-
[Unreleased]: https://github.com/codegress-com/arvo/compare/v0.1.0...HEAD
63+
[Unreleased]: https://github.com/codegress-com/arvo/compare/v1.0.0...HEAD
64+
[1.0.0]: https://github.com/codegress-com/arvo/compare/v0.1.1...v1.0.0
65+
[0.1.1]: https://github.com/codegress-com/arvo/compare/v0.1.0...v0.1.1
4366
[0.1.0]: https://github.com/codegress-com/arvo/releases/tag/v0.1.0

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "arvo"
3-
version = "0.9.0"
3+
version = "1.0.0"
44
license = "MIT"
55
description = "Validated, immutable value objects for common domain types (email, money, identifiers, …)"
66
authors = ["Codegress <hello@codegress.com>"]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Enable only the modules you need — unused features add zero dependencies.
7272

7373
| Feature | What you get | Extra deps |
7474
|:---|:---|:---|
75-
| `contact` | `EmailAddress`, `CountryCode`, `PhoneNumber`, `PostalAddress`, `Website` | `once_cell`, `regex`, `url` |
75+
| `contact` | `EmailAddress`, `CountryCode`, `PhoneNumber`, `PostalAddress`, `Website` | `regex`, `url` |
7676
| `finance` | `Money`, `CurrencyCode`, `Iban`, `Bic`, `VatNumber`, `Percentage`, `ExchangeRate`, `CreditCardNumber`, `CardExpiryDate` | `rust_decimal`, `chrono` |
7777
| `geo` | `Latitude`, `Longitude`, `Coordinate`, `BoundingBox`, `TimeZone`, `CountryRegion` ||
7878
| `measurement` | `Length`, `Weight`, `Temperature`, `Volume`, `Area`, `Speed`, `Pressure`, `Energy`, `Power`, `Frequency` ||

docs/contact.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Feature flag: `contact`
44

55
```toml
66
[dependencies]
7-
arvo = { version = "0.9", features = ["contact"] }
7+
arvo = { version = "1.0", features = ["contact"] }
88
```
99

1010
---
@@ -18,7 +18,7 @@ A validated, normalised email address.
1818

1919
```rust,ignore
2020
use arvo::contact::EmailAddress;
21-
use arvo::traits::ValueObject;
21+
use arvo::traits::{PrimitiveValue, ValueObject};
2222
2323
let email = EmailAddress::new("User@Example.COM".into())?;
2424
assert_eq!(email.value(), "user@example.com");
@@ -56,7 +56,7 @@ A validated ISO 3166-1 alpha-2 country code.
5656

5757
```rust,ignore
5858
use arvo::contact::CountryCode;
59-
use arvo::traits::ValueObject;
59+
use arvo::traits::{PrimitiveValue, ValueObject};
6060
6161
let code = CountryCode::new("cz".into())?;
6262
assert_eq!(code.value(), "CZ");
@@ -91,7 +91,7 @@ A validated phone number stored in canonical E.164 format.
9191

9292
```rust,ignore
9393
use arvo::contact::{CountryCode, PhoneNumber, PhoneNumberInput};
94-
use arvo::traits::ValueObject;
94+
use arvo::traits::{PrimitiveValue, ValueObject};
9595
9696
let phone = PhoneNumber::new(PhoneNumberInput {
9797
country_code: CountryCode::new("CZ".into())?,
@@ -145,7 +145,7 @@ A validated website URL. Accepts `http` and `https` schemes only. Scheme and hos
145145

146146
```rust,ignore
147147
use arvo::contact::Website;
148-
use arvo::traits::ValueObject;
148+
use arvo::traits::{PrimitiveValue, ValueObject};
149149
150150
let site = Website::new("https://EXAMPLE.COM/path".into())?;
151151
assert_eq!(site.value(), "https://example.com/path");
@@ -184,7 +184,7 @@ A validated composite postal address. All text fields are trimmed; empty or whit
184184

185185
```rust,ignore
186186
use arvo::contact::{CountryCode, PostalAddress, PostalAddressInput};
187-
use arvo::traits::ValueObject;
187+
use arvo::traits::{PrimitiveValue, ValueObject};
188188
189189
let addr = PostalAddress::new(PostalAddressInput {
190190
street: "Václavské náměstí 1".into(),

docs/finance.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Feature flag: `finance`
44

55
```toml
66
[dependencies]
7-
arvo = { version = "0.9", features = ["finance"] }
7+
arvo = { version = "1.0", features = ["finance"] }
88
```
99

1010
---
@@ -18,7 +18,7 @@ A validated ISO 4217 alphabetic currency code.
1818

1919
```rust,ignore
2020
use arvo::finance::CurrencyCode;
21-
use arvo::traits::ValueObject;
21+
use arvo::traits::{PrimitiveValue, ValueObject};
2222
2323
let code = CurrencyCode::new("eur".into())?;
2424
assert_eq!(code.value(), "EUR");
@@ -54,7 +54,7 @@ A validated monetary amount with an associated currency.
5454

5555
```rust,ignore
5656
use arvo::finance::{CurrencyCode, Money, MoneyInput};
57-
use arvo::traits::ValueObject;
57+
use arvo::traits::{PrimitiveValue, ValueObject};
5858
5959
let money = Money::new(MoneyInput {
6060
amount: "10.50".parse()?,
@@ -94,7 +94,7 @@ A validated IBAN (International Bank Account Number) using the mod-97 algorithm.
9494

9595
```rust,ignore
9696
use arvo::finance::Iban;
97-
use arvo::traits::ValueObject;
97+
use arvo::traits::{PrimitiveValue, ValueObject};
9898
9999
let iban = Iban::new("GB82 WEST 1234 5698 7654 32".into())?;
100100
assert_eq!(iban.value(), "GB82WEST12345698765432");
@@ -133,7 +133,7 @@ A validated BIC (Bank Identifier Code / SWIFT code).
133133

134134
```rust,ignore
135135
use arvo::finance::Bic;
136-
use arvo::traits::ValueObject;
136+
use arvo::traits::{PrimitiveValue, ValueObject};
137137
138138
let bic = Bic::new("DEUTDEDB".into())?;
139139
assert_eq!(bic.bank_code(), "DEUT");
@@ -166,7 +166,7 @@ A validated EU VAT number.
166166

167167
```rust,ignore
168168
use arvo::finance::VatNumber;
169-
use arvo::traits::ValueObject;
169+
use arvo::traits::{PrimitiveValue, ValueObject};
170170
171171
let vat = VatNumber::new("CZ 1234 5678".into())?;
172172
assert_eq!(vat.value(), "CZ12345678");
@@ -192,7 +192,7 @@ A validated percentage in the range `0.0..=100.0`.
192192

193193
```rust,ignore
194194
use arvo::finance::Percentage;
195-
use arvo::traits::ValueObject;
195+
use arvo::traits::{PrimitiveValue, ValueObject};
196196
197197
let p = Percentage::new(42.5)?;
198198
assert_eq!(*p.value(), 42.5);
@@ -220,7 +220,7 @@ A validated currency exchange rate between two different currencies.
220220

221221
```rust,ignore
222222
use arvo::finance::{CurrencyCode, ExchangeRate, ExchangeRateInput};
223-
use arvo::traits::ValueObject;
223+
use arvo::traits::{PrimitiveValue, ValueObject};
224224
225225
let rate = ExchangeRate::new(ExchangeRateInput {
226226
from: CurrencyCode::new("EUR".into())?,
@@ -259,7 +259,7 @@ A validated credit card number using the Luhn algorithm.
259259

260260
```rust,ignore
261261
use arvo::finance::CreditCardNumber;
262-
use arvo::traits::ValueObject;
262+
use arvo::traits::{PrimitiveValue, ValueObject};
263263
264264
let card = CreditCardNumber::new("4532 0151 1283 0366".into())?;
265265
assert_eq!(card.last_four(), "0366");
@@ -288,7 +288,7 @@ A validated credit/debit card expiry date that is not in the past.
288288

289289
```rust,ignore
290290
use arvo::finance::CardExpiryDate;
291-
use arvo::traits::ValueObject;
291+
use arvo::traits::{PrimitiveValue, ValueObject};
292292
293293
let exp = CardExpiryDate::new("12/28".into())?;
294294
assert_eq!(exp.value(), "12/28");

docs/geo.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Feature flag: `geo`
44

55
```toml
66
[dependencies]
7-
arvo = { version = "0.9", features = ["geo"] }
7+
arvo = { version = "1.0", features = ["geo"] }
88
```
99

1010
---
@@ -17,7 +17,7 @@ A validated geographic latitude in decimal degrees.
1717

1818
```rust,ignore
1919
use arvo::geo::Latitude;
20-
use arvo::traits::ValueObject;
20+
use arvo::traits::{PrimitiveValue, ValueObject};
2121
2222
let lat = Latitude::new(48.8588)?;
2323
assert_eq!(*lat.value(), 48.8588);
@@ -50,7 +50,7 @@ A validated geographic longitude in decimal degrees.
5050

5151
```rust,ignore
5252
use arvo::geo::Longitude;
53-
use arvo::traits::ValueObject;
53+
use arvo::traits::{PrimitiveValue, ValueObject};
5454
5555
let lng = Longitude::new(14.4208)?;
5656
assert_eq!(*lng.value(), 14.4208);
@@ -82,7 +82,7 @@ A geographic coordinate (latitude + longitude pair).
8282

8383
```rust,ignore
8484
use arvo::geo::{Coordinate, CoordinateInput, Latitude, Longitude};
85-
use arvo::traits::ValueObject;
85+
use arvo::traits::{PrimitiveValue, ValueObject};
8686
8787
let coord = Coordinate::new(CoordinateInput {
8888
lat: Latitude::new(48.858844)?,
@@ -122,7 +122,7 @@ A geographic bounding box defined by a south-west and a north-east [`Coordinate`
122122

123123
```rust,ignore
124124
use arvo::geo::{BoundingBox, BoundingBoxInput, Coordinate, CoordinateInput, Latitude, Longitude};
125-
use arvo::traits::ValueObject;
125+
use arvo::traits::{PrimitiveValue, ValueObject};
126126
127127
let sw = Coordinate::new(CoordinateInput {
128128
lat: Latitude::new(48.0)?,
@@ -173,7 +173,7 @@ A validated IANA timezone name.
173173

174174
```rust,ignore
175175
use arvo::geo::TimeZone;
176-
use arvo::traits::ValueObject;
176+
use arvo::traits::{PrimitiveValue, ValueObject};
177177
178178
let tz = TimeZone::new("Europe/Prague".into())?;
179179
assert_eq!(tz.value(), "Europe/Prague");
@@ -210,7 +210,7 @@ A validated ISO 3166-2 subdivision code.
210210

211211
```rust,ignore
212212
use arvo::geo::CountryRegion;
213-
use arvo::traits::ValueObject;
213+
use arvo::traits::{PrimitiveValue, ValueObject};
214214
215215
let region = CountryRegion::new("cz-pr".into())?;
216216
assert_eq!(region.value(), "CZ-PR");

docs/identifiers.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Feature flag: `identifiers`
44

55
```toml
66
[dependencies]
7-
arvo = { version = "0.9", features = ["identifiers"] }
7+
arvo = { version = "1.0", features = ["identifiers"] }
88
```
99

1010
---
@@ -18,7 +18,7 @@ A URL-safe slug: lowercase alphanumeric characters and hyphens only.
1818

1919
```rust,ignore
2020
use arvo::identifiers::Slug;
21-
use arvo::traits::ValueObject;
21+
use arvo::traits::{PrimitiveValue, ValueObject};
2222
2323
let slug = Slug::new("Hello-World".into())?;
2424
assert_eq!(slug.value(), "hello-world");
@@ -56,7 +56,7 @@ A validated EAN-13 barcode number.
5656

5757
```rust,ignore
5858
use arvo::identifiers::Ean13;
59-
use arvo::traits::ValueObject;
59+
use arvo::traits::{PrimitiveValue, ValueObject};
6060
6161
let ean = Ean13::new("4006381333931".into())?;
6262
assert_eq!(ean.value(), "4006381333931");
@@ -89,7 +89,7 @@ A validated EAN-8 barcode number.
8989

9090
```rust,ignore
9191
use arvo::identifiers::Ean8;
92-
use arvo::traits::ValueObject;
92+
use arvo::traits::{PrimitiveValue, ValueObject};
9393
9494
let ean = Ean8::new("73513537".into())?;
9595
assert_eq!(ean.value(), "73513537");
@@ -122,7 +122,7 @@ A validated ISBN-13 number.
122122

123123
```rust,ignore
124124
use arvo::identifiers::Isbn13;
125-
use arvo::traits::ValueObject;
125+
use arvo::traits::{PrimitiveValue, ValueObject};
126126
127127
let isbn = Isbn13::new("978-0-306-40615-7".into())?;
128128
assert_eq!(isbn.value(), "9780306406157");
@@ -156,7 +156,7 @@ A validated ISBN-10 number.
156156

157157
```rust,ignore
158158
use arvo::identifiers::Isbn10;
159-
use arvo::traits::ValueObject;
159+
use arvo::traits::{PrimitiveValue, ValueObject};
160160
161161
let isbn = Isbn10::new("0-306-40615-2".into())?;
162162
assert_eq!(isbn.value(), "0306406152");
@@ -190,7 +190,7 @@ A validated ISSN (International Standard Serial Number).
190190

191191
```rust,ignore
192192
use arvo::identifiers::Issn;
193-
use arvo::traits::ValueObject;
193+
use arvo::traits::{PrimitiveValue, ValueObject};
194194
195195
let issn = Issn::new("0317-8471".into())?;
196196
assert_eq!(issn.value(), "0317-8471");
@@ -224,7 +224,7 @@ A validated Vehicle Identification Number (VIN) per ISO 3779.
224224

225225
```rust,ignore
226226
use arvo::identifiers::Vin;
227-
use arvo::traits::ValueObject;
227+
use arvo::traits::{PrimitiveValue, ValueObject};
228228
229229
let vin = Vin::new("1HGBH41JXMN109186".into())?;
230230
assert_eq!(vin.wmi(), "1HG");

0 commit comments

Comments
 (0)