Beverage Label Formatter
Relevant source files
The following files were used as context for generating this wiki page:
The Beverage Label Formatter is a core module within the @cellarnode/beverage-utils library designed to convert technical slugs and classification data into human-readable labels. It provides a standardized way to display beverage categories and subtypes, ensuring consistency across different frontend frameworks and backend services.
The system relies on a combination of a lookup map (the LabelMap) and fallback logic that humanizes technical identifiers if a direct mapping is unavailable. This ensures that even in the absence of complete classification data, the user interface remains readable and professional.
Sources: README.md:1-5, src/format.ts
Core Data Structures
The formatter operates on standardized data types defined by the CellarNode classification system.
Beverage Classification Model
The system expects data structured into categories, each containing specific subtypes.
| Interface | Field | Type | Description |
|---|---|---|---|
BeverageSubtype | id | string | The technical slug (e.g., "red"). |
name | string | The display name (e.g., "Red Wine"). | |
BeverageCategory | id | string | The technical slug (e.g., "wine"). |
name | string | The display name (e.g., "Still Wine"). | |
subtypes | BeverageSubtype[] | List of nested subtypes. |
Sources: src/types.ts:1-17
Label Map Architecture
The LabelMap is a flat Record<string, string> used for high-speed lookups. It is generated via the buildLabelMap function, which creates three types of keys for every classification entry:
- Category ID: Maps category slugs to names.
- Subtype ID: Maps subtype slugs to names (last-write-wins for duplicates).
- Composite Key: Maps
category:subtypeto subtype names to ensure unambiguous lookups.
Sources: src/label-map.ts:5-15, README.md:31-40
Formatting Logic
The formatting system consists of two primary functions: formatBeverageLabel and formatBeverageType.
formatBeverageLabel
This function handles the conversion of a single key into a display string. If a LabelMap is provided and contains the key, it returns the mapped value. Otherwise, it "humanizes" the slug by replacing underscores with spaces and converting to Title Case.
Sources: src/format.ts:3-10, README.md:42-50
formatBeverageType
This function formats a full beverage classification, typically displaying it as "Category / Subtype". It is designed to handle disambiguation using composite keys (e.g., distinguishing "Red" under "Still Wine" vs "Red" under "Sparkling Wine").
Sources: src/format.ts:12-23, README.md:52-61
Normalization and Sanitization
Before labels are formatted or compared, the system provides utilities to normalize input strings. The normalizeToken function ensures that identifiers are deterministic by removing diacritics and standardizing separators.
| Step | Operation | Example Result |
|---|---|---|
| 1 | NFD Normalization | Côte -> Côte |
| 2 | Strip Diacritics | Côte -> Cote |
| 3 | Trim & Lowercase | SPAIN -> spain |
| 4 | Collapse Whitespace/Underscores | red_wine -> red-wine |
| 5 | Strip Leading/Trailing Hyphens | --foo-- -> foo |
Sources: src/normalize.ts:7-18
Integration with Frameworks
The formatter is designed to be used in conjunction with TanStack Query hooks in React, Vue, and Angular. These hooks fetch classification data from the CellarNode API and cache the resulting LabelMap.
Summary
The Beverage Label Formatter provides a robust, fail-safe mechanism for displaying industry-standard beverage classifications. By utilizing composite keys for disambiguation and providing intelligent string humanization fallbacks, it ensures that beverage information is always presented clearly to users, regardless of the completeness of the underlying data source.
Sources: README.md:1-10, src/format.ts:1-23