# retail.sku-generate Builds a stock-keeping unit code from a product family prefix and the variant's attributes, so the same product and options always give the same SKU: `generateSku("TSH", ["Navy Blue", "Large", "Cotton"], 3)` is `"TSH-NAV-LAR-COT"`. ## The scheme 1. Each part (the prefix, then each attribute in the order given) keeps only the ASCII letters and digits `A-Z a-z 0-9`, in order. Spaces, punctuation and every non-ASCII character are dropped. 2. What is left is uppercased. 3. Each attribute, not the prefix, is cut to its first `segmentLength` characters. `0` keeps it whole. 4. The parts are joined with `-`. An empty prefix is left out. Filtering happens before uppercasing on purpose: German sharp s uppercases to "SS" in all three languages, so uppercasing first would turn "Straße" into `STRASSE` in some places and `STRAE` in others. Here it is always `STRAE`. Accented letters are dropped, not transliterated ("Crème" is `CRME`); run the attribute through `text.slugify` first if you want `CREME`. ## What it does not do It does not guarantee uniqueness. Two attributes that agree in their first `segmentLength` characters collide ("Brown" and "Bronze" are both `BRO` at 3), and so do "10.5" and "105" (both `105`). A SKU scheme with a fixed segment length needs a catalogue-level check, or a longer segment, and that belongs to whoever owns the catalogue. The order of the attributes is part of the SKU, so fix it per product family (colour, then size, then material). ## Errors No attributes, a negative `segmentLength`, or a prefix or attribute with no letters or digits at all (`"***"`) are errors, because a SKU with an empty segment would silently collide with its neighbours.