TCGPlayer Suffix-Based Parsing
| Date | 2026-03-24 |
| Status | Accepted |
| Decision Makers | @benjaminW78 |
Context and Problem Statement
TCGCSV product names for SWU cards follow a consistent suffix pattern to indicate variant and finish. We need a reliable way to parse these product names into a base card name, variant, and finish so we can create the correct printing records and match against the SWU API for enrichment.
TCGCSV provides several fields per product: name, subTypeName, productId, and boolean flags. However, subTypeName is inconsistent across sets. In some TCGCSV groups, subTypeName is "Normal" / "Foil". In others, it’s "Unit" / "Event" / "Leader" (card type instead of finish). This makes subTypeName unreliable for determining whether a product is Standard, Hyperspace, Foil, etc.
The product names consistently use a suffix pattern:
"Darth Vader - Dark Lord of the Sith"— Standard Normal (no suffix)"Darth Vader - Dark Lord of the Sith (Foil)"— Standard Foil"Darth Vader - Dark Lord of the Sith (Hyperspace)"— Hyperspace Normal"Darth Vader - Dark Lord of the Sith (Hyperspace Foil)"— Hyperspace Foil"Darth Vader - Dark Lord of the Sith (Showcase)"— Showcase Foil"Darth Vader - Dark Lord of the Sith (Prestige)"— Prestige Normal"Darth Vader - Dark Lord of the Sith (Prestige Foil)"— Prestige Foil"Darth Vader - Dark Lord of the Sith (Serialized)"— Prestige Serialized
Decision Drivers
subTypeNamefrom TCGCSV is inconsistent and cannot be relied upon- Product name suffixes are consistent across all SWU sets on TCGPlayer
- We need to determine the exact variant+finish combo for each TCGCSV product
- The solution should be maintainable and type-safe
Considered Options
- Suffix-based parsing: Parse the product name suffix and map it to variant+finish via a static map
- subTypeName parsing: Use the
subTypeNamefield to determine variant/finish - Boolean flag matching: Use TCGCSV boolean flags (if available) to determine card properties
Decision Outcome
Chosen option: suffix-based parsing, implemented via two functions on the importer class: parseTcgProductName() to extract the base name and suffix, and resolveVariantAndFinish() to map the suffix to the corresponding variant and finish enums.
The suffix constants are defined in a TCG_PLAYER_SUFFIX_MAP:
private static readonly TCG_PLAYER_SUFFIX_MAP: Record<string, Record<string, string | null>> = {
[StarWarsUnlimitedVariant.STANDARD]: {
[StarWarsUnlimitedFinish.NORMAL]: null, // no suffix
[StarWarsUnlimitedFinish.FOIL]: "Foil",
},
[StarWarsUnlimitedVariant.HYPERSPACE]: {
[StarWarsUnlimitedFinish.NORMAL]: "Hyperspace",
[StarWarsUnlimitedFinish.FOIL]: "Hyperspace Foil",
},
[StarWarsUnlimitedVariant.SHOWCASE]: {
[StarWarsUnlimitedFinish.FOIL]: "Showcase",
},
[StarWarsUnlimitedVariant.PRESTIGE]: {
[StarWarsUnlimitedFinish.NORMAL]: "Prestige",
[StarWarsUnlimitedFinish.FOIL]: "Prestige Foil",
[StarWarsUnlimitedFinish.SERIALIZED]: "Serialized",
},
}The parsing algorithm:
parseTcgProductName()strips all known suffixes (checked in longest-first order viaTCG_PLAYER_SUFFIXES) from the product name to extract the base name and suffixresolveVariantAndFinish()looks up the suffix in a reverse map built fromTCG_PLAYER_SUFFIX_MAPto determine the variant and finish- The base name is then normalized (lowercased, accent-stripped) and used to match against the SWU API enrichment index
Parsing Flow
Impacted Files
| File | Key Symbols | Role |
|---|---|---|
packages/games/game-importer/src/star-wars-unlimited-importer.ts | TCG_PLAYER_SUFFIX_MAP, TCG_PLAYER_SUFFIXES, parseTcgProductName(), resolveVariantAndFinish(), normalizeCardName() | Defines the suffix map, the ordered suffixes array, and the parsing/resolution functions |
Consequences
Positive
- Works reliably across all SWU sets — product name suffixes are consistent
- Single source of truth for the suffix-to-variant+finish mapping
- Type-safe: enum keys prevent typos and make the map exhaustive
- Enables the TCGCSV-first architecture — every TCGCSV product can be parsed into variant+finish without relying on the SWU API
Negative
- Relies on TCGPlayer maintaining their naming convention — if they change suffix patterns, the map needs updating
- New suffixes (e.g., a future “Ultra Foil” variant) require a code change to add to both the map and the suffixes array
- Does not handle edge cases where card names themselves contain parentheses (mitigated by only recognizing known suffixes)