Khải aaa2b032ad docs: add guidelines for porting branded string types (#395)
* docs(agents): add guidance for porting branded string types

Document how to translate TypeScript pnpm's branded string types,
string-literal unions, and template literal types into pacquet:
declare a newtype wrapper, match upstream's validation discipline
(`TryFrom`/`FromStr`, with `from_str_unchecked` only when upstream
uses an `as` cast), wire serde when the value crosses a file
boundary, and prefer `enum`s for string-literal unions.

https://claude.ai/code/session_01U5wP1SGLNZVNNL3qFDvxq7

* docs(agents): cover unvalidated brands and `derive_more` for conversions

Add two notes to the branded-string-types porting section:

- Some upstream brands exist purely for type-safety and never validate
  at runtime; in that case the Rust wrapper should expose `From<String>`
  rather than a `TryFrom`.
- When the resulting `From` / `Into` impls are trivial wrap/unwrap
  one-liners, derive them with `derive_more` instead of writing the
  `impl` block by hand.

https://claude.ai/code/session_01U5wP1SGLNZVNNL3qFDvxq7

* docs(agents): tighten branded-string-types section per writing style

Restructure the new section to follow the writing style in
`CONTRIBUTING.md`: remove mid-sentence em dashes by splitting clauses
into their own sentences, replace `e.g.` with "for example" where the
shortened form was carrying a long parenthetical, and drop the
ambiguous `un-checked` hyphenation in favor of `unchecked`. Render the
template literal example as inline HTML so the literal backticks
display without relying on triple-backtick fencing inside a list item.

https://claude.ai/code/session_01U5wP1SGLNZVNNL3qFDvxq7

* docs(agents): revert template literal example to triple-backtick form

The triple-backtick form is the canonical GFM way to embed a string
that itself contains backticks, and it renders correctly on GitHub.
The earlier switch to inline HTML was unnecessary.

https://claude.ai/code/session_01U5wP1SGLNZVNNL3qFDvxq7

* docs(agents): prefer borrowed `&'de str` for serde deserialization

The existing string-backed newtypes in pacquet use
`#[serde(try_from = "&'de str")]` (see `crates/lockfile/src/pkg_name.rs`
and `crates/lockfile/src/comver.rs`) so deserialization does not allocate
an owned `String` for every value. The new branded-string-types section
now recommends the same form by default and treats `try_from = "String"`
as the exception, used only when the validator genuinely needs an owned
input.

https://claude.ai/code/session_01U5wP1SGLNZVNNL3qFDvxq7

* docs(agents): drop the `try_from = "String"` fallback from rule 5

Rule 5 now recommends `#[serde(try_from = "&'de str")]` outright,
without the "fallback to `String` when an owned value is required"
caveat. The existing string-backed newtypes in pacquet all use the
borrowed form, so the simpler rule matches the codebase.

https://claude.ai/code/session_01U5wP1SGLNZVNNL3qFDvxq7

* docs(agents): use TypeScript's "type assertion" terminology

In TypeScript, `as` is a compile-time type assertion that performs no
runtime conversion. Saying "type-cast" or "cast" implies runtime
behavior, which the surrounding text is specifically calling out as
absent. Use "type assertion" / "assertion" instead.

https://claude.ai/code/session_01U5wP1SGLNZVNNL3qFDvxq7

* docs(agents): revert rule 5 to `try_from = "String"`

Use the owned-string form in the guideline. The borrowed-input form
saves an allocation but ties the wrapper's validator to a `&str`
input, which is more constraining when the validator wants ownership.
The guideline keeps the simpler shape; crates that need the borrowed
form can still adopt it locally.

https://claude.ai/code/session_01U5wP1SGLNZVNNL3qFDvxq7

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-06 12:58:02 +02:00
Description
No description provided
MIT 301 MiB
Languages
Rust 61.8%
TypeScript 37.7%
JavaScript 0.4%