Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Match structured IDs via a canonical identity helper, not raw equality
Parse structured domain identifiers by anchoring on a structural marker (known prefix/delimiter) rather than length/position guessing, normalize both sides to a canonical identity, and compare those — so values differing only in insignificant segments still match.
Bad example
| 1 | // Heuristic: 'if it has fewer than 5 parts treat it as a bare id'. |
| 2 | // Mis-parses 'FIA-818-X' (3 parts, but a bare id with a suffix) and breaks |
| 3 | // the moment a key format gains/loses a segment. |
| 4 | function couponIdentity(key: string): string { |
| 5 | const parts = key.split('-'); |
| 6 | if (parts.length < 5) { |
| 7 | return `${parts[0]}-${parts[1]}`; |
| 8 | } |
| 9 | return `${parts[2]}-${parts[3]}`; |
| 10 | } |
| 11 |
|
| 12 | // Comparing raw keys: a card that is genuinely the user's current plan |
| 13 | // fails to match because TYPE (MAGAZINE vs NEWSPAPER) or SUFFIX differs. |
| 14 | const isCurrent = offer.key === currentKey; |
Explanation (EN)
Guessing structure from segment count is brittle: any key whose format changes by one segment is mis-parsed, and 'FIA-818-X' is silently read wrong. Comparing raw keys means two values that are the same plan but differ in irrelevant segments (type, suffix, casing) won't match.
Objašnjenje (HR)
Pogađanje strukture iz broja segmenata je krhko: svaki ključ kojem se format promijeni za jedan segment se krivo parsira, a 'FIA-818-X' se tiho čita pogrešno. Usporedba sirovih ključeva znači da se dvije vrijednosti koje su isti plan ali se razlikuju u nebitnim segmentima (tip, sufiks, velika/mala slova) neće poklopiti.
Good example
| 1 | // Anchor on a structural marker; normalize both inputs to one canonical form. |
| 2 | // Full key: HM-{TYPE}-{CODE}-{NUMBER}-{SUFFIX}; host may pass bare {CODE}-{NUMBER}. |
| 3 | export function couponIdentity(key: string): string { |
| 4 | const parts = key.split('-'); |
| 5 | const [code, number] = |
| 6 | parts[0]?.toUpperCase() === 'HM' ? [parts[2], parts[3]] : [parts[0], parts[1]]; |
| 7 | return `${code ?? ''}-${number ?? ''}`.toUpperCase(); |
| 8 | } |
| 9 |
|
| 10 | // Compare canonical identities, so insignificant segments are ignored. |
| 11 | const isCurrent = |
| 12 | couponIdentity(offer.key) === couponIdentity(currentKey); |
Explanation (EN)
Anchoring on the 'HM' prefix makes parsing deterministic regardless of how many trailing segments exist, and handles both full and bare forms. Normalizing both sides (uppercasing, dropping insignificant segments) means equality compares meaning, not surface text. The significant segments are documented in a comment.
Objašnjenje (HR)
Sidrenje na 'HM' prefiks čini parsiranje determinističkim bez obzira na broj završnih segmenata i obrađuje i puni i goli oblik. Normalizacija obje strane (velika slova, izbacivanje nebitnih segmenata) znači da usporedba uspoređuje značenje, a ne površinski tekst. Značajni segmenti su dokumentirani u komentaru.
Notes (EN)
Pair the helper with table-style unit tests that lock in the significant-vs-ignored segment semantics (same identity across differing TYPE/SUFFIX; distinct identity for a different campaign number; bare form unchanged).
Bilješke (HR)
Upari helper s tabličnim unit testovima koji fiksiraju semantiku značajnih vs ignoriranih segmenata (ista identitet preko različitih TYPE/SUFFIX; različit identitet za drugi broj kampanje; goli oblik nepromijenjen).