[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of countries-data/packages/usa/vtex.country-data-settings/configuration.json from the countries-data VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "countryISO": "USA",
  "addressFields": {
    "country": {
      "label": "country",
      "hidden": true,
      "maxLength": 100
    },
    "state": {
      "label": "stateAbbreviation",
      "maxLength": 100,
      "required": true,
      "options": [
        {
          "label": "AL",
          "value": "AL"
        },
        {
          "label": "AK",
          "value": "AK"
        },
        {
          "label": "AZ",
          "value": "AZ"
        },
        {
          "label": "AR",
          "value": "AR"
        },
        {
          "label": "CA",
          "value": "CA"
        },
        {
          "label": "CO",
          "value": "CO"
        },
        {
          "label": "CT",
          "value": "CT"
        },
        {
          "label": "DE",
          "value": "DE"
        },
        {
          "label": "DC",
          "value": "DC"
        },
        {
          "label": "FL",
          "value": "FL"
        },
        {
          "label": "GA",
          "value": "GA"
        },
        {
          "label": "HI",
          "value": "HI"
        },
        {
          "label": "ID",
          "value": "ID"
        },
        {
          "label": "IL",
          "value": "IL"
        },
        {
          "label": "IN",
          "value": "IN"
        },
        {
          "label": "IA",
          "value": "IA"
        },
        {
          "label": "KS",
          "value": "KS"
        },
        {
          "label": "KY",
          "value": "KY"
        },
        {
          "label": "LA",
          "value": "LA"
        },
        {
          "label": "ME",
          "value": "ME"
        },
        {
          "label": "MD",
          "value": "MD"
        },
        {
          "label": "MA",
          "value": "MA"
        },
        {
          "label": "MI",
          "value": "MI"
        },
        {
          "label": "MN",
          "value": "MN"
        },
        {
          "label": "MS",
          "value": "MS"
        },
        {
          "label": "MO",
          "value": "MO"
        },
        {
          "label": "MT",
          "value": "MT"
        },
        {
          "label": "NE",
          "value": "NE"
        },
        {
          "label": "NV",
          "value": "NV"
        },
        {
          "label": "NH",
          "value": "NH"
        },
        {
          "label": "NJ",
          "value": "NJ"
        },
        {
          "label": "NM",
          "value": "NM"
        },
        {
          "label": "NY",
          "value": "NY"
        },
        {
          "label": "NC",
          "value": "NC"
        },
        {
          "label": "ND",
          "value": "ND"
        },
        {
          "label": "OH",
          "value": "OH"
        },
        {
          "label": "OK",
          "value": "OK"
        },
        {
          "label": "OR",
          "value": "OR"
        },
        {
          "label": "PA",
          "value": "PA"
        },
        {
          "label": "PR",
          "value": "PR"
        },
        {
          "label": "RI",
          "value": "RI"
        },
        {
          "label": "SC",
          "value": "SC"
        },
        {
          "label": "SD",
          "value": "SD"
        },
        {
          "label": "TN",
          "value": "TN"
        },
        {
          "label": "TX",
          "value": "TX"
        },
        {
          "label": "UT",
          "value": "UT"
        },
        {
          "label": "VT",
          "value": "VT"
        },
        {
          "label": "VA",
          "value": "VA"
        },
        {
          "label": "WA",
          "value": "WA"
        },
        {
          "label": "WV",
          "value": "WV"
        },
        {
          "label": "WI",
          "value": "WI"
        },
        {
          "label": "WY",
          "value": "WY"
        }
      ]
    },
    "city": {
      "label": "city",
      "maxLength": 100,
      "required": true
    },
    "neighborhood": {
      "label": "neighborhood",
      "hidden": true,
      "maxLength": 100
    },
    "street": {
      "label": "streetRoadAvenue",
      "required": true
    },
    "number": {
      "label": "numberOption",
      "maxLength": 750,
      "hidden": true,
      "autoComplete": "off"
    },
    "complement": {
      "label": "complement",
      "maxLength": 750
    },
    "reference": {
      "label": "reference",
      "hidden": true,
      "maxLength": 750
    },
    "receiverName": {
      "label": "receiverName",
      "elementName": "receiver",
      "maxLength": 750,
      "required": true
    },
    "postalCode": {
      "label": "postalCode",
      "forgottenURL": "https://tools.usps.com/go/ZipLookupAction_input"
    }
  },
  "display": {
    "minimal": [
      [
        {
          "name": "postalCode"
        }
      ]
    ],
    "compact": [
      [
        {
          "name": "street"
        }
      ],
      [
        {
          "name": "city"
        },
        {
          "delimiter": " ",
          "name": "state"
        },
        {
          "delimiter": " ",
          "name": "postalCode"
        }
      ]
    ],
    "extended": [
      [
        {
          "name": "receiverName"
        }
      ],
      [
        {
          "name": "street"
        },
        {
          "delimiter": " ",
          "name": "complement"
        }
      ],
      [
        {
          "name": "number"
        },
        {
          "delimiter": ", ",
          "name": "neighborhood"
        }
      ],
      [
        {
          "name": "city"
        },
        {
          "delimiter": " ",
          "name": "state"
        },
        {
          "delimiter": " ",
          "name": "postalCode"
        }
      ]
    ]
  },
  "phone": {
    "countryCode": "1",
    "mask": "999-999-9999",
    "pattern": "/^(?:(?:(?:\\+|)(?:1|))|)(?:1|)(?:2(?:0[1-9]|1[02-9]|2[4-9]|3[1469]|4[089]|5[01-46]|6[0279]|7[0468]|8[139])|3(?:0[1-9]|1[02-9]|2[01235]|3[014679]|4[01367]|5[12]|6[01459]|8[056])|4(?:0[1-9]|1[02-9]|2[345]|3[0-24578]|4[023578]|5[08]|6[49]|7[0589]|8[04]|50[1-57-9])|5(?:0[1-9]|1[02-9]|20|3[014]|4[01]|5[179]|6[1-47]|7[013-59]|8[01567])|6(?:0[1-9]|1[0234-9]|2[036-8]|3[0169]|4[167]|5[0179]|6[01279]|7[0189]|8[1249])|7(?:0[1-9]|1[2-9]|2[047]|3[01247]|4[07]|5[247]|6[02-59]|7[02-589]|8[01567])|8(?:0[1-8]|1[0-9]|28|3[0-25]|4[3578]|5[06-9]|6[02-57]|7[0238])|9(?:0[1-9]|1[02-9]|2[0578]|3[15-9]|4[0179]|5[124679]|7[0-3589]|8[045]|89))\\d{7}$/"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of countries-data/packages/bra/vtex.country-data-settings/configuration.json from the countries-data VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "countryISO": "BRA",
  "addressFields": {
    "country": {
      "label": "country",
      "hidden": true,
      "maxLength": 100
    },
    "state": {
      "label": "stateAbbreviation",
      "maxLength": 100,
      "required": true,
      "optionsCaption": "UF",
      "options": [
        {
          "label": "AC",
          "value": "AC"
        },
        {
          "label": "AL",
          "value": "AL"
        },
        {
          "label": "AP",
          "value": "AP"
        },
        {
          "label": "AM",
          "value": "AM"
        },
        {
          "label": "BA",
          "value": "BA"
        },
        {
          "label": "CE",
          "value": "CE"
        },
        {
          "label": "DF",
          "value": "DF"
        },
        {
          "label": "ES",
          "value": "ES"
        },
        {
          "label": "GO",
          "value": "GO"
        },
        {
          "label": "MA",
          "value": "MA"
        },
        {
          "label": "MT",
          "value": "MT"
        },
        {
          "label": "MS",
          "value": "MS"
        },
        {
          "label": "MG",
          "value": "MG"
        },
        {
          "label": "PA",
          "value": "PA"
        },
        {
          "label": "PB",
          "value": "PB"
        },
        {
          "label": "PR",
          "value": "PR"
        },
        {
          "label": "PE",
          "value": "PE"
        },
        {
          "label": "PI",
          "value": "PI"
        },
        {
          "label": "RJ",
          "value": "RJ"
        },
        {
          "label": "RN",
          "value": "RN"
        },
        {
          "label": "RS",
          "value": "RS"
        },
        {
          "label": "RO",
          "value": "RO"
        },
        {
          "label": "RR",
          "value": "RR"
        },
        {
          "label": "SC",
          "value": "SC"
        },
        {
          "label": "SP",
          "value": "SP"
        },
        {
          "label": "SE",
          "value": "SE"
        },
        {
          "label": "TO",
          "value": "TO"
        }
      ]
    },
    "city": {
      "label": "city",
      "maxLength": 100,
      "required": true
    },
    "neighborhood": {
      "label": "neighborhood",
      "maxLength": 100,
      "required": true
    },
    "street": {
      "label": "streetRoadAvenue",
      "required": true
    },
    "number": {
      "label": "numberOption",
      "maxLength": 750,
      "required": true,
      "autoComplete": "off"
    },
    "complement": {
      "label": "complement",
      "maxLength": 750
    },
    "reference": {
      "label": "reference",
      "hidden": true,
      "maxLength": 750
    },
    "receiverName": {
      "label": "receiverName",
      "elementName": "receiver",
      "maxLength": 750,
      "required": true
    },
    "postalCode": {
      "mask": "99999-999",
      "pattern": "^(\\d){5}-?(\\d){3}$",
      "label": "postalCode",
      "forgottenURL": "https://buscacepinter.correios.com.br/app/endereco/index.php"
    }
  },
  "display": {
    "minimal": [
      [
        {
          "name": "postalCode"
        }
      ]
    ],
    "compact": [
      [
        {
          "name": "street"
        },
        {
          "delimiter": " ",
          "name": "number"
        }
      ],
      [
        {
          "name": "neighborhood"
        }
      ],
      [
        {
          "name": "city"
        },
        {
          "delimiter": " - ",
          "name": "state"
        }
      ],
      [
        {
          "name": "postalCode"
        }
      ]
    ],
    "extended": [
      [
        {
          "name": "receiverName"
        }
      ],
      [
        {
          "name": "street"
        },
        {
          "delimiter": " ",
          "name": "number"
        }
      ],
      [
        {
          "name": "complement"
        }
      ],
      [
        {
          "name": "neighborhood"
        }
      ],
      [
        {
          "name": "city"
        },
        {
          "delimiter": " - ",
          "name": "state"
        }
      ],
      [
        {
          "name": "postalCode"
        }
      ]
    ]
  },
  "phone": {
    "countryCode": "55",
    "mask": "(99) 9 9999-9999",
    "pattern": "^(?:(?:(?:\\+|)(?:55|)|))(?:0|)(?:(?:(?:1[1-9]|2[12478]|3[1-8]|6[1-9]|7[134579]|8[1-9]|9[1-9]|4[1-9]|5[1-5])(?:9\\d{8}|\\d{8})))$"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of countries-data/packages/bol/vtex.country-data-settings/configuration.json from the countries-data VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "countryISO": "BOL",
  "addressFields": {
    "country": {
      "hidden": true,
      "maxLength": 100,
      "label": "country"
    },
    "street": {
      "label": "street",
      "required": true
    },
    "number": {
      "maxLength": 750,
      "label": "number",
      "required": true,
      "autoComplete": "off"
    },
    "complement": {
      "maxLength": 750,
      "label": "complement"
    },
    "reference": {
      "hidden": true,
      "maxLength": 750,
      "label": "reference"
    },
    "receiverName": {
      "elementName": "receiver",
      "maxLength": 750,
      "label": "receiverName",
      "required": true
    }
  },
  "display": {
    "minimal": [
      [
        {
          "name": "city"
        }
      ]
    ],
    "compact": [
      [
        {
          "name": "street"
        },
        {
          "delimiter": " ",
          "name": "number"
        }
      ],
      [
        {
          "name": "city"
        }
      ]
    ],
    "extended": [
      [
        {
          "name": "receiverName"
        }
      ],
      [
        {
          "name": "street"
        },
        {
          "delimiter": " ",
          "name": "number"
        }
      ],
      [
        {
          "name": "complement"
        }
      ],
      [
        {
          "name": "city"
        }
      ]
    ]
  },
  "locationSelect": {
    "countryData": {
      "Beni": {
        "Cercado": {
          "Paititi": "10000",
          "Trinidad": "10001",
          "Yucumo": "10002"
        },
        "José Ballivián": {
          "Reyes": "10100",
          "Rurrenabaque": "10101",
          "San Borja": "10102"
        },
        "Mamore": {
          "San Ramon": "10200"
        },
        "Moxos": {
          "San Ignacio de Moxos": "10300",
          "San Joaquin": "10301"
        },
        "Vaca Díez": {
          "Guayaramerín": "10400",
          "Magdalena": "10401",
          "Riberalta": "10402"
        },
        "Yacuma": {
          "Santa Ana del Yacuma": "10500",
          "Santa Rosa de Yacuma": "10501"
        }
      },
      "Chuquisaca": {
        "Nor Cinti": {
          "Pelillojo": "20000"
        },
        "Luis Calvo": {
          "Machareti": "20100"
        },
        "Hernando Siles": {
          "Monteagudo": "20200"
        },
        "Oropeza": {
          "Yotala": "20300"
        },
        "Sucre": {
          "Sucre": "20400"
        }
      },
      "Cochabamba": {
        "Arani": {
          "Arani": "30000",
          "Vacas": "30001"
        },
        "Ayopaya": {
          "Morochata": "30100",
          "Villa Indedencia": "30101"
        },
        "Capinota": {
          "Capinota": "30200",
          "Irpa Irpa": "30201",
          "La Cantera": "30202"
        },
        "Carrasco": {
          "Bulo Bulo": "30300",
          "Chimoré": "30301",
          "Entre Ríos": "30302",
          "Ivirgarzama": "30303",
          "Puerto Villaroel": "30304",
          "Totora": "30305",
          "Villa Tunari": "30306"
        },
        "Cercado": {
          "Cochabamba": "30400"
        },
        "Chapare": {
          "Colomi": "30500",
          "Epizana": "30501",
          "Eterazama": "30502",
          "Huayllani": "30503",
          "Sacaba": "30504",
          "San Gabriel": "30505",
          "Shinaota": "30506"
        },
        "Esteban Arze": {
          "Anzaldo": "30600",
          "Arbieto": "30601",
          "Tarata": "30602"
        },
        "Germán Jordán": {
          "Cliza": "30700"
        },
        "Mizque": {
          "Mizque": "30800"
        },
        "Narciso Campero": {
          "Aiquile": "30900"
        },
        "Punata": {
          "Punata": "31000",
          "San Benito": "31001",
          "Valle Alto": "31002"
        },
        "Quillacollo": {
          "Apote": "31100",
          "Colcapirhua": "31101",
          "Quillacollo": "31102",
          "Sipe Sipe": "31103",
          "Tapacarí": "31104",
          "Tiquipaya": "31105",
          "Vinto": "31106"
        },
        "Tiraque": {
          "Tiraque": "31200"
        }
      },
      "La Paz": {
        "Aroma": {
          "Ayo Ayo": "40000",
          "Capaja": "40001",
          "Patacamaya": "40002",
          "Pucara": "40003",
          "Sica Sica": "40004"
        },
        "Camacho": {
          "Escoma": "40100",
          "Mocomoco": "40101",
          "Puerto Acosta": "40102"
        },
        "Caranavi": {
          "Caranavi": "40200",
          "Taipiplaya": "40201"
        },
        "Franz Tamayo": {
          "Apolo": "40300"
        },
        "Ingavi": {
          "Calamarca": "40400",
          "Desaguadero": "40401",
          "Guaqui": "40402",
          "Jesus de Machaca": "40403",
          "Tiahuanacu": "40404",
          "Viacha": "40405"
        },
        "Inquisivi": {
          "Colquiri": "40500",
          "Quime": "40501"
        },
        "La Paz": {
          "Achacachi": "40600"
        },
        "Larecaja": {
          "Guanay": "40700",
          "Mapiri": "40701",
          "Mayaya": "40702",
          "Sorata": "40703",
          "Tacacoma": "40704",
          "Tipuani": "40705"
        },
        "Los Andes": {
          "Batallas": "40800",
          "El Lago": "40801",
          "Laja": "40802",
          "Pucarani": "40803"
        },
        "Manco Kapac": {
          "Copacabana": "40900",
          "Tiquina San Pablo": "40901"
        },
        "Murillo": {
          "Palca": "41000"
        },
        "Muñecas": {
          "Chuma": "41100"
        },
        "Nor Yungas": {
          "Coripata": "41200",
          "Coroico": "41201"
        },
        "Omasuyos": {
          "Ancoraimes": "41300",
          "Huarina": "41301"
        },
        "Pacajes": {
          "Charaña": "41400"
        },
        "Pedro Domingo Murillo": {
          "Achocalla": "41500",
          "El Alto": "41501",
          "La Paz": "41502",
          "Valencia": "41503"
        },
        "Sud Yungas": {
          "Chulumani": "41600",
          "Irupana": "41601",
          "Ixiamas": "41602",
          "La Asunta": "41603",
          "Palos Blancos": "41604"
        },
        "Yungas": {
          "Cruz Loma": "41700"
        }
      },
      "Oruro": {
        "Cercado": {
          "Caracollo": "50000",
          "Oruro": "50001"
        },
        "Oruro": {
          "Challapata": "50100"
        },
        "Pantaleón Dalence": {
          "Huanuni": "50200"
        },
        "Poopo": {
          "Poopo": "50300"
        },
        "Sebastián Pagador": {
          "Santiago de Huari": "50400"
        }
      },
      "Pando": {
        "Nicolás Suárez": {
          "Cobija": "60000",
          "El Porvenir": "60001"
        }
      },
      "Potosí": {
        "Antonio Quijarro": {
          "Uyuni": "70000"
        },
        "Linares": {
          "Puna": "70100"
        },
        "Modesto Omiste": {
          "Villazón": "70200"
        },
        "Rafael Bustillo": {
          "Llallagua": "70300",
          "Siglo XX": "70301",
          "Uncia": "70302"
        },
        "Saavedra": {
          "Betanzos": "70400"
        },
        "Sud Chichas": {
          "Tupiza": "70500"
        },
        "Tomás Frías": {
          "Plahipo": "70600",
          "Potosí": "70601",
          "Pulquipunta": "70602"
        }
      },
      "Santa Cruz": {
        "Andrés Ibañez": {
          "Buena Vista": "80000",
          "Cotoca": "80001",
          "El Carmen Rivero Torrez": "80002",
          "El Torno": "80003",
          "Jorochito": "80004",
          "La Angostura": "80005",
          "La Guardia": "80006",
          "Paurito": "80007",
          "Porongo": "80008",
          "San Jose del Torno": "80009",
          "Santa Cruz": "80010",
          "Santa Marta": "80011",
          "Santa Rita": "80012"
        },
        "Angel Sandóval": {
          "San Matías": "80100"
        },
        "Caballero": {
          "Comarapa": "80200",
          "Palizada": "80201",
          "Saipina": "80202"
        },
        "Chiquitos": {
          "Cañada Larga": "80300",
          "Chihuahua": "80301",
          "Pailas": "80302",
          "Pailón": "80303",
          "Roboré": "80304",
          "San José de Chiquitos": "80305"
        },
        "Cordillera": {
          "Abapo": "80400",
          "Basilio": "80401",
          "Boyuibe": "80402",
          "Cabezas": "80403",
          "Camiri": "80404",
          "Charagua": "80405",
          "Gutierrez": "80406",
          "Mora": "80407",
          "Rio Seco": "80408",
          "Zanja Honda": "80409"
        },
        "Florida": {
          "Mairana": "80500",
          "Mataral": "80501",
          "Samaipata": "80502"
        },
        "Germán Bush": {
          "Puerto Suárez": "80600"
        },
        "Guarayos": {
          "Ascensión de Guarayos": "80700",
          "El Puente": "80701",
          "Urubichá": "80702",
          "Yotau": "80703"
        },
        "Ichilo": {
          "Buen Retiro": "80800",
          "Nuevo Horizontes": "80801",
          "San Carlos": "80802",
          "Santa fe de Yapacani": "80803",
          "Yapacani": "80804"
        },
        "Ignacio Warnes": {
          "Okinawa": "80900",
          "Okinawa 2": "80901",
          "Warnes": "80902"
        },
        "José Miguel de Velasco": {
          "San Ignacio": "81000",
          "San Rafael": "81001",
          "TX San Antonio": "81002",
          "TX Santa Ana": "81003"
        },
        "Manuel María Caballero": {
          "Pulquina": "81100"
        },
        "Ñuflo de Chávez": {
          "4 Cañadas": "81200",
          "Cerro Pelado": "81201",
          "Concepción": "81202",
          "Los Troncos": "81203",
          "Puerto Rico": "81204",
          "San Javier": "81205",
          "San Juan de Yapacaní": "81206",
          "San Julian": "81207",
          "San Ramón": "81208"
        },
        "Obispo Santiesteban": {
          "Canandoa": "81300",
          "Chané": "81301",
          "Colonia Pirai": "81302",
          "Hardeman": "81303",
          "Litoral": "81304",
          "Mineros": "81305",
          "Montero": "81306",
          "Saavedra": "81307",
          "San Pedro": "81308"
        },
        "Sara": {
          "Portachuelo": "81400",
          "Puente San Pablo": "81401",
          "Santa Rosa del Sara": "81402"
        },
        "Valle Grande": {
          "Trigal": "81500",
          "Vallegrande": "81501"
        },
        "Velasco": {
          "San Miguel de Velasco": "81600"
        }
      },
      "Tarija": {
        "Aniceto Arce": {
          "Padcaya": "90000"
        },
        "Burnet O'Connor": {
          "Entre Rios": "90100"
        },
        "Cercado": {
          "Tarija": "90200"
        },
        "Gran Chaco": {
          "Sanandita": "90300"
        },
        "Méndez": {
          "Canasmoro": "90400",
          "San Lorenzo": "90401",
          "Tomatitas": "90402"
        },
        "Tarija": {
          "Bermejo": "90500",
          "Villamontes": "90501",
          "Yacuiba": "90502"
        }
      }
    },
    "fields": [
      {
        "name": "state",
        "label": "department"
      },
      {
        "name": "city",
        "label": "province"
      },
      {
        "name": "neighborhood",
        "label": "city"
      }
    ]
  },
  "phone": {
    "countryCode": "591",
    "mask": "9 999-9999",
    "pattern": "/^(?:(?:(?:\\+|)591)|)(?:0|)[23467]\\d{7}$/"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/messages/pt.json from the store-link VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.link.label.title": "Texto do link",
  "admin/editor.link.label.description": "Qualquer texto ex. \"Categorias\", \"Sobre nós\", etc.",
  "admin/editor.link.href.description": "URL para o link ex. \"https://www.google.com\", \"/sobre-nos\", etc",
  "admin/editor.product-link.title": "Link de produto",
  "admin/editor.link.target.title": "Onde abrir o link",
  "admin/editor.link.target.description": "Você pode checar as opções disponíveis em: https://developer.mozilla.org/docs/Web/HTML/Element/a",
  "admin/editor.link.rel.attribute.title": "\"rel\" atributo",
  "admin/editor.link.rel.attribute.description": "Você pode checar as opções disponíveis em: https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types"
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/messages/en.json from the store-link VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.link.label.title": "Link text",
  "admin/editor.link.label.description": "Any text e.g. \"Categories\", \"About us\", etc.",
  "admin/editor.link.href.description": "The actual link e.g. \"https://www.google.com\", \"/about-us\", etc",
  "admin/editor.product-link.title": "Product Link",
  "admin/editor.link.target.title": "Where to open the link",
  "admin/editor.link.target.description": "You can check the options available at: https://developer.mozilla.org/docs/Web/HTML/Element/a",
  "admin/editor.link.rel.attribute.title": "\"rel\" attribute",
  "admin/editor.link.rel.attribute.description": "You can check the options available at: https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/messages/context.json from the store-link VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.link.label.title": "Link text",
  "admin/editor.link.label.description": "Any text e.g. \"Categories\", \"About us\", etc.",
  "admin/editor.link.href.description": "The actual link e.g. \"https://www.google.com\", \"/about-us\", etc",
  "admin/editor.product-link.title": "Product Link",
  "admin/editor.link.target.title": "Where to open the link",
  "admin/editor.link.target.description": "You can check the options available at: https://developer.mozilla.org/docs/Web/HTML/Element/a",
  "admin/editor.link.rel.attribute.title": "\"rel\" attribute",
  "admin/editor.link.rel.attribute.description": "You can check the options available at: https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types"
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/messages/es.json from the store-link VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.link.label.title": "Texto del link",
  "admin/editor.link.label.description": "Cualquier mensaje de texto p. Ej. \"Categorías \", \"Acerca de nosotros \", etc.",
  "admin/editor.link.href.description": "El Link real, p. \"https://www.google.com\", \"/about-us \", etc.",
  "admin/editor.product-link.title": "Link de producto",
  "admin/editor.link.target.title": "Donde abrir el link",
  "admin/editor.link.target.description": "Puede consultar las opciones disponibles en: https://developer.mozilla.org/docs/Web/HTML/Element/a",
  "admin/editor.link.rel.attribute.title": "\"rel\" atributo",
  "admin/editor.link.rel.attribute.description": "Puedes consultar las opciones disponibles aquí: https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/docs/README.md from the store-link VTEX app.

[Assistant]
Here's the implementation:

```markdown
📢 Use this project, [contribute](https://github.com/vtex-apps/product-summary) to it or open issues to help evolve it using [Store Discussion](https://github.com/vtex-apps/store-discussion).

# Store Link

<!-- DOCS-IGNORE:start -->
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
<!-- DOCS-IGNORE:end -->

The Store Link app provides blocks for displaying links in other theme blocks, such as Product Summary.

![image](https://cdn.jsdelivr.net/gh/vtexdocs/dev-portal-content@main/images/vtex-store-link-0.png)

## Configurating the store link

1. Add the `store-link` app to your theme dependencies in the `manifest.json` file. Then, you can use all the [blocks](#blocks) exported by the `store-link` app and its respective [props](#props).

```diff
  "dependencies": {
+   "vtex.store-link": "0.x"
  }
```

2. Choose one of the [blocks](#blocks) exported by the `store-link` app and declare it in the block where the link will be displayed. See below an example of a `link.product` being used in the [`product-summary`](https://developers.vtex.com/docs/apps/vtex.product-summary) block to display the "More details" link.

```jsonc
{
  "link.product#product-page": {
    "props": {
      "href": "/{slug}/p",
      "label": "More details >"
    }
  },
  "product-summary.shelf": {
    "children": [
      "product-summary-image",
      "product-summary-name",
      "product-rating-inline",
      "product-summary-space",
      "product-summary-price",
      "link.product#product-page"
    ]
  },
}
```
> ⚠ Note that you must place the `link.product` block inside a block that provides a product context (e.g., [`ProductSummary`](https://developers.vtex.com/docs/apps/vtex.product-summary)). From the previous example, note that a `{slug}` placeholder is being passed onto the `href` prop. When rendered, this placeholder is overwritten by the value accrued from the closest product context, generating a link like `/everyday-necessaire/p`.

## Blocks

| Block          | Description                                      |
| -------------- | ------------------------------------------------ |
| `link.product` | A link that uses the product context, such as a product slug or department. For example, `/{slug}/p`.       |
| `link`         | A regular link that does not require the product context to function. For example, `/home`. |

## Props

All blocks exported by `store-link` share the same props:

| Prop name         | Type     | Description                                                                                | Default value                         |
| ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------- |
| `label`           | `string` | Link text.                                                                                | `undefined`                           |
| `href`            | `string` | Link URL.                                                                                | `#`                                   |
| `scrollTo`        | `string` | Element anchor to scroll after navigation. (E.g. `"#footer"`)                                                                                | `undefined`                           |
| `target`          | `string` | Where the linked URL will be displayed. This prop works the same way as the target from [HTML `<a>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a). Since the [*anchor* element's target](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-target) default is `_self`, this prop will be set to `_self` if it is undefined. | `undefined`                           |
| `displayMode`     | `enum`   | How the link will be displayed. Possible values are: `anchor` (displays a normal link with no styles) or `button` (displays a button that can be customized using the `buttonProps` prop).                                                                                | `anchor`                              |
| `buttonProps`     | `object` | How the link button will be displayed. Use this prop only when the `displayMode` prop is set as `button`.                                                                                | `{ variant: primary, size: regular }` |
| `escapeLinkRegex` | `string` | RegExp, with global match, used to remove special characters within product specifications (e.g., if you want to use `/[%]/g` then `escapeLinkRegex` = `[%]`).                                                                                | `undefined`                           |
| `rel`             | `string` | This prop specifies the relationship between the current document and linked ones for better SEO. This prop works the same way as the `rel` attribute from `<a>`, the [HTML anchor element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a). You can see supported values [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types).       | `undefined`                           |

- `buttonProps` object:

| Prop name | Type   | Description                                                                                | Default value |
| --------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `variant` | `enum` | Link button that has visual prominence. Possible values are: `primary` or `secondary` (values are set following the [VTEX Styleguide](https://styleguide.vtex.com/#/Components/Forms/Button)). | `primary`     |
| `size`    | `enum` | Link button size. Possible values are: `small`, `regular` or `large` (values are set following the [VTEX Styleguide](https://styleguide.vtex.com/#/Components/Forms/Button)).                  | `regular`     |

## App Behavior

When creating an URL link using the `href` prop, you can add custom query string values, as shown in the example below:

```json
{
  "link#foo": {
    "props": {
      "href": "/login?returnUrl={queryString.returnUrl}",
      "label": "Sign in"
    }
  }
}
```

Considering the `href` prop from the previous example, note that the URL link will be built correctly if the current page has the `returnUrl` query string. Otherwise, it will be built with an empty value.

Depending on the context that the `link.product` block uses, you can use product variables to structure different URL paths for the `href` prop. For example, you could create a link to a specific product department (`/{department}`).

| Product variable | Description                                    |
| ---------------- | ---------------------------------------------- |
| `brand`          | Product brand name.                            |
| `brandId`        | Product brand ID.                              |
| `category1`      | Highest level category in the category tree.   |
| `category2`      | Second highest level category.                 |
| `category3`      | Third highest level category.                  |
| `category4`      | Fourth highest level category.                 |
| `department`     | Product department.                            |
| `productId`      | Product ID.                                    |
| `skuId`          | Currently selected SKU ID.                     |
| `slug`           | The link text used to create the product link. |

To build URLs with variables related to product specifications, use the following format: `{specificationGroups.groupName.specifications.specificationName}`. Replace `groupName` and `specificationName` with the specification group and the product specification names accordingly. For example:

```jsonc
{
  "link.product#vtex": {
    "props": {
      "href": "{specificationGroups.Design.specifications.Dimensions}",
      "label": "VTEX"
    }
  }
}
```

In the example above, `Design` is the specification group name, and `Dimensions` is the product specification name.

## Customization

To apply CSS customizations in this and other blocks, see the [Using CSS handles for store customization](https://developers.vtex.com/docs/guides/vtex-io-documentation-using-css-handles-for-store-customization) guide. All blocks have the same handles.

| CSS handles         |
| ------------------- |
| `childrenContainer` |
| `label`             |
| `link`              |

<!-- DOCS-IGNORE:start -->

## Contributors ✨

Thanks goes to these wonderful people:

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tr>
    <td align="center"><a href="https://github.com/anto90fg"><img src="https://avatars.githubusercontent.com/u/73878310?v=4?s=100" width="100px;" alt=""/><br /><sub><b>anto90fg</b></sub></a><br /><a href="https://github.com/vtex-apps/store-link/commits?author=anto90fg" title="Code">💻</a></td>
  </tr>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome!

<!-- DOCS-IGNORE:end -->

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/react/ProductLink.tsx from the store-link VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useMemo } from 'react'
import classnames from 'classnames'
import { Link } from 'vtex.render-runtime'
import { useCssHandles } from 'vtex.css-handles'
import { useProduct } from 'vtex.product-context'
import { formatIOMessage } from 'vtex.native-types'
import { useIntl } from 'react-intl'

import { Props, defaultButtonProps } from './StoreLink'
import hasChildren from './modules/hasChildren'
import { AvailableContext } from './modules/mappings'
import useButtonClasses from './modules/useButtonClasses'
import { useInterpolatedLink } from './modules/useInterpolatedLink'

const CSS_HANDLES = [
  'link',
  'label',
  'childrenContainer',
  'buttonLink',
] as const

function ProductLink(props: Props) {
  const {
    label,
    href,
    escapeLinkRegex,
    children,
    target,
    displayMode = 'anchor',
    buttonProps = defaultButtonProps,
    rel,
  } = props

  const intl = useIntl()
  const productContext = useProduct()
  const handles = useCssHandles(CSS_HANDLES)

  const extraContexts = useMemo(() => {
    return [
      {
        type: AvailableContext.product,
        context: productContext,
      },
    ]
  }, [productContext])

  const memoizedEscapeLinkRegex = useMemo(() => {
    if (!escapeLinkRegex) {
      return undefined
    }

    return new RegExp(escapeLinkRegex, 'g')
  }, [escapeLinkRegex])

  const resolvedLink = useInterpolatedLink(
    href,
    memoizedEscapeLinkRegex,
    extraContexts
  )

  const localizedLabel = formatIOMessage({
    id: label,
    intl,
  })

  const {
    size = defaultButtonProps.size,
    variant = defaultButtonProps.variant,
  } = buttonProps
  const classes = useButtonClasses({ variant, size })

  const rootClasses = classnames(handles.link, {
    [`${handles.buttonLink} ${classes.container}`]: displayMode === 'button',
  })

  const labelClasses = classnames(handles.label, {
    [classes.label]: displayMode === 'button',
  })

  return (
    <Link target={target} to={resolvedLink} className={rootClasses} rel={rel}>
      {label && <span className={labelClasses}>{localizedLabel}</span>}
      {hasChildren(children) && displayMode === 'anchor' && (
        <div className={handles.childrenContainer}>{children}</div>
      )}
    </Link>
  )
}

ProductLink.schema = { title: 'admin/editor.product-link.title' }

export default ProductLink

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/react/package.json from the store-link VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "scripts": {
    "lint": "tsc --noEmit && eslint --quiet --fix --ext ts,tsx .",
    "test": "vtex-test-tools test"
  },
  "dependencies": {
    "@vtex/slugify": "^1.0.3",
    "classnames": "^2.2.6",
    "react": "^16.8.6",
    "react-apollo": "^2.5.8",
    "react-dom": "^16.8.6",
    "react-intl": "^3.11.0"
  },
  "devDependencies": {
    "@apollo/react-testing": "^4.0.0",
    "@types/classnames": "^2.2.9",
    "@types/graphql": "^14.5.0",
    "@types/jest": "^25.1.0",
    "@types/node": "^13.1.8",
    "@types/react": "^16.9.19",
    "@vtex/test-tools": "^3.3.2",
    "@vtex/tsconfig": "^0.4.4",
    "husky": "^5.0.9",
    "typescript": "3.9.7",
    "vtex.css-handles": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@0.4.4/public/@types/vtex.css-handles",
    "vtex.native-types": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.native-types@0.7.5/public/@types/vtex.native-types",
    "vtex.product-context": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-context@0.10.0/public/@types/vtex.product-context",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.131.0/public/@types/vtex.render-runtime",
    "vtex.store-link": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-link@0.7.6/public/@types/vtex.store-link"
  },
  "version": "0.9.5"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/react/StoreLink.tsx from the store-link VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import classnames from 'classnames'
import { Link } from 'vtex.render-runtime'
import { defineMessages, useIntl } from 'react-intl'
import { useCssHandles } from 'vtex.css-handles'
import { formatIOMessage } from 'vtex.native-types'

import hasChildren from './modules/hasChildren'
import useButtonClasses, { Variant } from './modules/useButtonClasses'
import { useInterpolatedLink } from './modules/useInterpolatedLink'

type DisplayMode = 'anchor' | 'button'
type Size = 'small' | 'regular' | 'large'

export interface ButtonProps {
  variant: Variant
  size: Size
}

// https://stackoverflow.com/a/49725198/11274053
type RequireOnlyOne<T, Keys extends keyof T = keyof T> = Pick<
  T,
  Exclude<keyof T, Keys>
> &
  {
    [K in Keys]-?: Required<Pick<T, K>> &
      Partial<Record<Exclude<Keys, K>, undefined>>
  }[Keys]

interface AllProps {
  href?: string
  label: string
  target?: string
  scrollTo?: string
  escapeLinkRegex?: string
  children: React.ReactNode
  displayMode?: DisplayMode
  buttonProps?: Partial<ButtonProps>
  rel?: string
}

export type Props = RequireOnlyOne<AllProps, 'label' | 'children'>

defineMessages({
  labelTitle: {
    id: 'admin/editor.link.label.title',
    defaultMessage: '',
  },
})

export const defaultButtonProps: ButtonProps = {
  variant: 'primary',
  size: 'regular',
}

const CSS_HANDLES = ['link', 'label', 'childrenContainer', 'buttonLink']

function StoreLink(props: Props) {
  const {
    label,
    href,
    target,
    children,
    buttonProps = defaultButtonProps,
    scrollTo,
    displayMode = 'anchor',
    rel,
  } = props
  const { variant, size } = {
    ...defaultButtonProps,
    ...buttonProps,
  }
  const intl = useIntl()
  const handles = useCssHandles(CSS_HANDLES)
  const classes = useButtonClasses({
    variant,
    size,
  })
  const resolvedLink = useInterpolatedLink(href)

  const rootClasses = classnames(handles.link, {
    [`${handles.buttonLink} ${classes.container}`]: displayMode === 'button',
  })

  const labelClasses = classnames(handles.label, {
    [classes.label]: displayMode === 'button',
  })

  const scrollOptions = scrollTo ? { baseElementId: scrollTo } : undefined

  const localizedLabel = formatIOMessage({
    id: label,
    intl,
  })

  return (
    <Link
      to={resolvedLink}
      target={target}
      className={rootClasses}
      scrollOptions={scrollOptions}
      rel={rel}
    >
      {label && <span className={labelClasses}>{localizedLabel}</span>}
      {hasChildren(children) && (
        <div className={handles.childrenContainer}>{children}</div>
      )}
    </Link>
  )
}

StoreLink.schema = {
  title: 'Link',
}

export default StoreLink

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/store/contentSchemas.json from the store-link VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "definitions": {
    "StoreLink": {
      "title": "Link",
      "type": "object",
      "required": [
        "href",
        "label"
      ],
      "properties": {
        "label": {
          "title": "admin/editor.link.label.title",
          "description": "admin/editor.link.label.description",
          "$ref": "app:vtex.native-types#/definitions/text"
        },
        "href": {
          "title": "Link",
          "type": "string",
          "description": "admin/editor.link.href.description"
        },
        "target": {
          "title": "admin/editor.link.target.title",
          "type": "string",
          "description": "admin/editor.link.target.description"
        },
        "rel": {
          "title": "admin/editor.link.rel.attribute.title",
          "type": "string",
          "description": "admin/editor.link.rel.attribute.description"
        }
      }
    },
    "ProductLink": {
      "title": "admin/editor.product-link.title",
      "$ref": "app:vtex.store-link#/definitions/StoreLink"
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/store/interfaces.json from the store-link VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "link": {
    "component": "StoreLink",
    "composition": "children",
    "content": {
      "$ref": "app:vtex.store-link#/definitions/StoreLink"
    }
  },
  "link.product": {
    "component": "ProductLink",
    "composition": "children",
    "content": {
      "$ref": "app:vtex.store-link#/definitions/ProductLink"
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/react/typings/types.ts from the store-link VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ProductTypes } from 'vtex.product-context'

import { AvailableContext } from '../modules/mappings'

// https://stackoverflow.com/questions/46176165/ways-to-get-string-literal-type-of-array-values-without-enum-overhead
const inferType = <T extends string>(...args: T[]) => args

const productVariables = inferType(
  'slug',
  'skuId',
  'department',
  'category1',
  'category2',
  'category3',
  'category4',
  'productId',
  'brand',
  'brandId'
)
export type ProductVariable = typeof productVariables[0]

export const PRODUCT_VARIABLES: ProductVariable[] = [
  'slug',
  'skuId',
  'department',
  'category1',
  'category2',
  'category3',
  'category4',
  'productId',
  'brand',
  'brandId',
]

export interface Context {
  type: AvailableContext
  namespace?: string
  context:
    | Partial<ProductTypes.ProductContextState>
    | Record<string, any>
    | undefined
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/react/__tests__/ProductLink.test.tsx from the store-link VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { screen, render } from '@vtex/test-tools/react'
import { useProduct } from 'vtex.product-context'

import ProductLink from '../ProductLink'

const mockedUseProduct = useProduct as jest.Mock

function mockProduct({ brand, specificationGroups = [] }: any) {
  mockedUseProduct.mockImplementation(() => {
    return {
      selectedItem: { itemId: 'itemId' },
      product: {
        categories: ['category1', 'category2'],
        specificationGroups,
        linkText: 'linkText',
        productId: 'productId',
        brand,
        brandId: 'brandId',
      },
    }
  })
}

test('slugifies interpolated brand name', () => {
  mockProduct({
    brand: 'brand name with lots of spaces',
  })

  render(<ProductLink href="/custom-link-{brand}" label="See brand" />)

  expect(screen.getByText('See brand').closest('a')).toHaveAttribute(
    'href',
    '/custom-link-brand-name-with-lots-of-spaces'
  )
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/react/modules/hasChildren.ts from the store-link VTEX app.

[Assistant]
Here's the implementation:

```typescript
import React, { Children } from 'react'

export default function hasChildren(children: React.ReactNode) {
  if (!children) {
    return false
  }

  return Children.toArray(children).length > 0
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/react/modules/mappings.ts from the store-link VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { searchSlugify } from '@vtex/slugify'
import type { ProductTypes } from 'vtex.product-context'

import { PRODUCT_VARIABLES, ProductVariable } from '../typings/types'

function mapCategories(rawCategories: string[]) {
  const categoriesSorted = rawCategories
    .slice()
    .sort((a, b) => a.length - b.length)

  return categoriesSorted
    .map(categories => {
      return categories
        .replace(/^\//, '')
        .replace(/\/$/, '')
        .split('/')
        .reverse()[0]
    })
    .filter(Boolean)
}

interface SpecificationGroup {
  originalName: string
  specifications?: Array<{ originalName?: string; values: string[] }>
}

function mapSpecifications(specificationGroups: SpecificationGroup[]) {
  const mappedSpecifications: Record<string, string> = {}
  specificationGroups.forEach(
    ({ originalName: groupName, specifications = [] }) => {
      specifications.forEach(({ originalName: specificationName, values }) => {
        const key = `specificationGroups.${groupName}.specifications.${specificationName}`
        const [value] = values
        mappedSpecifications[key] = value ?? ''
      })
    }
  )

  return mappedSpecifications
}

export function mapProductValues(
  context: Partial<ProductTypes.ProductContextState> | undefined
) {
  const { product, selectedItem } = context ?? {}

  if (!product) {
    return {}
  }

  if (!selectedItem) {
    return {}
  }

  const categories = mapCategories(product.categories)
  const specifications = mapSpecifications(product.specificationGroups)
  const variables: Record<Partial<ProductVariable>, string | number> = {
    slug: product.linkText,
    skuId: selectedItem.itemId,
    department: categories[0],
    category1: categories[1],
    category2: categories[2],
    category3: categories[3],
    category4: categories[4],
    productId: product.productId,
    brand: searchSlugify(product.brand),
    brandId: product.brandId,
  }

  const output: Record<string, string> = specifications
  for (const key of PRODUCT_VARIABLES) {
    if (variables[key]) {
      if (typeof variables[key] === 'number') {
        output[key] = variables[key].toString()
      } else {
        output[key] = variables[key] as string
      }
    }
  }

  return output
}

function mapQueryStringValues(context?: Record<string, any>) {
  return context ?? {}
}

export enum AvailableContext {
  product = 'product',
  queryString = 'queryString',
}

export function getMappingFn(
  contextType: AvailableContext
): typeof mapProductValues | typeof mapQueryStringValues {
  switch (contextType) {
    case AvailableContext.product:
      return mapProductValues
    case AvailableContext.queryString:
      return mapQueryStringValues
    default:
      return () => ({})
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/react/modules/useButtonClasses.ts from the store-link VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useMemo } from 'react'
import classnames from 'classnames'

import { ButtonProps } from '../StoreLink'

export type Variant = 'primary' | 'secondary'

interface Options {
  variant?: Variant
  disabled?: boolean
  size?: ButtonProps['size']
}

const LINK_CLASSES = 'inline-flex items-center no-underline'
const BASE_CONTAINER_CLASSES = 'bw1 fw5 ba v-mid pa0 lh-solid br2'
const LABEL_BASE = 'w-100 tc'

const PRIMARY_ENABLED =
  'bg-action-primary b--action-primary c-on-action-primary hover-bg-action-primary hover-b--action-primary hover-c-on-action-primary'
const PRIMARY_DISABLED = 'bg-disabled b--muted-5 c-on-disabled'

const SECONDARY_ENABLED =
  'bg-action-secondary b--action-secondary c-on-action-secondary hover-bg-action-secondary hover-b--action-secondary hover-c-on-action-secondary'

const SMALL = 'min-h-small t-action--small'
const REGULAR = 'min-h-regular t-action'
const LARGE = 'min-h-large t-action--large'
const LABEL_SMALL = 'ph5'
const LABEL_REGULAR = 'ph6'
const LABEL_LARGE = 'ph7'

function getClassesByVariant(variant: Variant, disabled: boolean) {
  let container

  // eslint-disable-next-line default-case
  switch (variant) {
    case 'primary':
      container = disabled ? PRIMARY_DISABLED : PRIMARY_ENABLED
      break
    case 'secondary':
      container = SECONDARY_ENABLED
      break
  }

  return { container }
}

function getClassesBySize(size: ButtonProps['size']) {
  let container
  let label

  switch (size) {
    case 'small':
      container = SMALL
      label = LABEL_SMALL
      break
    case 'large':
      container = LARGE
      label = LABEL_LARGE
      break
    default:
      container = REGULAR
      label = LABEL_REGULAR
      break
  }

  return { container, label }
}

export default function useButtonClasses(options: Options) {
  return useMemo(() => {
    const { variant = 'primary', disabled = false, size = 'regular' } = options
    const variantClasses = getClassesByVariant(variant, disabled)
    const sizeClasses = getClassesBySize(size)
    const classes = {
      container: classnames(
        BASE_CONTAINER_CLASSES,
        LINK_CLASSES,
        variantClasses.container,
        sizeClasses.container
      ),
      label: classnames(LABEL_BASE, sizeClasses.label),
    }

    return classes
  }, [options])
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/react/modules/useInterpolatedLink.ts from the store-link VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useRuntime } from 'vtex.render-runtime'
import { useEffect, useState } from 'react'

import interpolateLink from './interpolateLink'
import { AvailableContext } from './mappings'
import type { Context } from '../typings/types'

export const useInterpolatedLink = (
  href?: string,
  escapeLinkRegex?: RegExp,
  extraContexts?: Context[]
) => {
  const [resolvedLink, setResolvedLink] = useState('#')
  const {
    route: { queryString },
  } = useRuntime()

  useEffect(() => {
    if (!href) {
      return
    }

    const contexts: Context[] = [
      {
        type: AvailableContext.queryString,
        namespace: 'queryString',
        context: queryString,
      },
      ...(extraContexts ?? []),
    ]

    const newLink = contexts.reduce((acc, contextInfo) => {
      return interpolateLink({
        link: acc,
        namespace: contextInfo.namespace,
        context: contextInfo.context,
        contextType: contextInfo.type,
        escapeLinkRegex,
      })
    }, href)

    setResolvedLink(newLink)
  }, [href, escapeLinkRegex, extraContexts, queryString])

  return resolvedLink
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-link/react/modules/interpolateLink.ts from the store-link VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { getMappingFn, AvailableContext } from './mappings'
import type { Context } from '../typings/types'

interface Params {
  link: string
  namespace?: string
  context: Context['context']
  contextType: AvailableContext
  escapeLinkRegex?: RegExp
}

export default function interpolateLink(params: Params) {
  const { link, namespace, context, contextType, escapeLinkRegex } = params

  const mapValues = getMappingFn(contextType)
  const variables = mapValues(context)

  let resolvedLink = link

  for (const key of Object.keys(variables)) {
    let newKey = key
    if (escapeLinkRegex) {
      newKey = key.replace(escapeLinkRegex, '')
    }
    const regex = new RegExp(
      `{${namespace ? `${namespace}.${newKey}` : newKey}}`,
      'g'
    )

    // we slugify the context value so we don't end up with invalid characters on the URL
    resolvedLink = resolvedLink.replace(regex, variables[key])
  }
  // Replace not found variables with empty string
  if (namespace) {
    const missingKeys = new RegExp(`{${namespace}.(.*)}`)
    resolvedLink = resolvedLink.replace(missingKeys, () => '')
  }

  return resolvedLink
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/configuration/schema.json from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "definitions": {
    "addressDisplay": {
      "type": "array",
      "items": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "city",
                "complement",
                "country",
                "neighborhood",
                "number",
                "postalCode",
                "receiverName",
                "reference",
                "state",
                "street"
              ]
            },
            "delimiter": { "type": "string" },
            "delimiterAfter": { "type": "string" }
          },
          "required": ["name"]
        }
      }
    },
    "addressField": {
      "type": "object",
      "properties": {
        "label": { "type": "string" },
        "name": {
          "type": "string",
          "enum": [
            "addressType",
            "city",
            "complement",
            "country",
            "neighborhood",
            "number",
            "postalCode",
            "receiverName",
            "reference",
            "state",
            "street"
          ]
        },
        "hidden": { "type": "boolean" },
        "maxLength": { "type": "number" },
        "size": { "type": "string" },
        "required": { "type": "boolean" },
        "autoComplete": { "type": "string" },
        "optionsCaption": { "type": "string" },
        "options": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "label": { "type": "string" },
              "value": { "type": "string" }
            }
          }
        },
        "elementName": { "type": "string" },
        "mask": {
          "type": "string",
          "description": "Optional mask to format the field for display."
        },
        "pattern": {
          "type": "string",
          "description": "Regex used for the field validation."
        }
      },
      "required": ["label"]
    }
  },
  "type": "object",
  "properties": {
    "countryISO": { "type": "string" },
    "addressFields": {
      "type": "object",
      "properties": {
        "country": { "$ref": "#/definitions/addressField" },
        "street": { "$ref": "#/definitions/addressField" },
        "number": { "$ref": "#/definitions/addressField" },
        "complement": { "$ref": "#/definitions/addressField" },
        "reference": { "$ref": "#/definitions/addressField" },
        "neighborhood": { "$ref": "#/definitions/addressField" },
        "state": { "$ref": "#/definitions/addressField" },
        "city": { "$ref": "#/definitions/addressField" },
        "receiverName": { "$ref": "#/definitions/addressField" },
        "postalCode": {
          "allOf": [
            { "$ref": "#/definitions/addressField" },
            { "properties": { "forgottenURL": { "type": "string" } } }
          ]
        }
      }
    },
    "display": {
      "type": "object",
      "properties": {
        "minimal": {
          "$ref": "#/definitions/addressDisplay"
        },
        "compact": {
          "$ref": "#/definitions/addressDisplay"
        },
        "extended": {
          "$ref": "#/definitions/addressDisplay"
        }
      },
      "required": ["minimal", "compact", "extended"]
    },
    "locationSelect": {
      "type": "object",
      "properties": {
        "countryData": { "type": "object" },
        "fields": {
          "type": "array",
          "items": { "$ref": "#/definitions/addressField" }
        }
      }
    },
    "phone": {
      "type": "object",
      "properties": {
        "countryCode": {
          "type": "string",
          "description": "The country calling code. E.g.: 55 for Brazil and 1 for USA"
        },
        "mask": {
          "type": "string",
          "description": "Phone number mask for value display."
        },
        "pattern": {
          "type": "string",
          "description": "Regex used for the phone number validation"
        }
      },
      "required": ["countryCode", "pattern"]
    },
    "legalPersonTaxId": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of the document in the specific country. E.g.: Cadastro Nacional da Pessoa Jurídica for Brazil and Employer Identification Number for the USA"
        },
        "abbreviation": {
          "type": "string",
          "description": "Abbreviation for the document name, such as CNPJ for Brazil."
        },
        "mask": {
          "type": "string",
          "description": "Tax ID mask for value display"
        }
      },
      "required": ["name", "abbreviation", "mask"]
    }
  },
  "required": ["countryISO", "addressFields", "display", "phone"]
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/graphql/schema.graphql from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```graphql
scalar JSON
scalar JSONObject

# https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/
type LegalPersonTaxIdData {
  name: String!
  abbreviation: String!
  mask: String!
}

type PhoneData {
  countryCode: String!
  mask: String
  pattern: String!
}

type DisplayDefinition {
  name: String!
  delimiter: String
  delimiterAfter: String
}

type DisplayData {
  minimal: [[DisplayDefinition!]!]!
  compact: [[DisplayDefinition!]!]!
  extended: [[DisplayDefinition!]!]!
}

type AddressFieldsData {
  city: Field
  complement: Field
  country: Field
  neighborhood: Field
  number: Field
  postalCode: Field
  receiverName: Field
  reference: Field
  state: Field
  street: Field
}

type LocationSelectData {
  fields: [Field!]!
  countryData: JSON
}

type CountryData {
  countryISO: String!
  addressFields: AddressFieldsData!
  display: DisplayData!
  locationSelect: LocationSelectData
  phone: PhoneData!
  legalPersonTaxId: LegalPersonTaxIdData
}

type Query {
  countryData(country: String!): CountryData
    @settings(settingsType: "workspace")
    @cacheControl(scope: PUBLIC, maxAge: SHORT)

  countriesData(countries: [String!]!): [CountryData!]!
    @settings(settingsType: "workspace")
    @cacheControl(scope: PUBLIC, maxAge: SHORT)

  allCountriesData: [CountryData!]!
    @settings(settingsType: "workspace")
    @cacheControl(scope: PUBLIC, maxAge: SHORT)
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/node/service.json from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "routes": {
    "countrySettings": {
      "path": "/country-settings/:country",
      "settingsType": "workspace",
      "access": "public",
      "policies": [
        {
          "effect": "allow",
          "actions": ["get"],
          "principals": ["vrn:apps:*:{{account}}:{{workspace}}:app/vtex.*"]
        }
      ]
    },
    "allCountrySettings": {
      "path": "/country-settings/",
      "settingsType": "workspace",
      "access": "public",
      "policies": [
        {
          "effect": "allow",
          "actions": ["get"],
          "principals": ["vrn:apps:*:{{account}}:{{workspace}}:app/vtex.*"]
        }
      ]
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/node/package.json from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "vtex.country-data-settings",
  "private": true,
  "license": "UNLICENSED",
  "devDependencies": {
    "@types/graphql-type-json": "^0.3.2",
    "@vtex/api": "6.41.0",
    "@vtex/tsconfig": "^0.5.0"
  },
  "dependencies": {
    "graphql": "^14.6.0",
    "graphql-type-json": "^0.3.2"
  },
  "version": "0.5.0"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/node/index.ts from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Service, method } from '@vtex/api'

import resolvers from './resolvers'
import { countrySettings } from './middlewares/countrySettings'
import { allCountrySettings } from './middlewares/allCountrySettings'

export default new Service({
  routes: {
    countrySettings: method({ GET: [countrySettings] }),
    allCountrySettings: method({ GET: [allCountrySettings] }),
  },
  graphql: {
    resolvers,
  },
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/graphql/types/Field.graphql from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```graphql
type PostalCodeData {
  forgottenURL: String
}

union AdditionalFieldData = PostalCodeData

type FieldOptionData {
  label: String!
  value: String!
}

type Field {
  label: String!
  name: String
  hidden: Boolean
  maxLength: Int
  size: String
  required: Boolean
  autoComplete: String
  optionsCaption: String
  options: [FieldOptionData!]
  elementName: String
  mask: String
  additionalData: AdditionalFieldData
  pattern: String
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/node/typings/global.d.ts from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare global {
  interface Configuration {
    declarer: string
    [declarerAppName: string]: CountryDataConfiguration
  }

  type AddressField =
    | 'city'
    | 'complement'
    | 'country'
    | 'neighborhood'
    | 'number'
    | 'postalCode'
    | 'receiverName'
    | 'reference'
    | 'state'
    | 'street'

  interface CountryDataConfiguration {
    countryISO: string
    addressFields: AddressFieldsConfiguration
    display: DisplayData
    phone: PhoneConfiguration
  }

  interface DisplayData {
    minimal: DisplayDefinition[][]
    compact: DisplayDefinition[][]
    expanded: DisplayDefinition[][]
  }

  interface DisplayDefinition {
    name: AddressField
    delimiter: string
    delimiterAfter: string
  }

  type PostalCodeField = AddressFieldsConfiguration & PostalCodeConfiguration

  interface AddressFieldsConfiguration {
    [field in AddressField]: AddressFieldConfiguration
    postalCode?: AddressFieldConfiguration & PostalCodeConfiguration
  }

  interface PostalCodeConfiguration {
    forgottenURL?: string
  }

  interface AddressFieldConfiguration {
    label: string
    name?: AddressField | 'addressType'
    hidden?: boolean
    maxLength?: number
    size?: string
    required?: boolean
    autoComplete?: string
    optionsCaption?: string
    options?: AddressOption[]
    elementName?: string
    mask?: string
  }

  interface AddressOption {
    label: string
    value: string
  }

  interface PhoneConfiguration {
    countryCode: string
    mask?: string
  }
}

export {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/node/middlewares/countrySettings.ts from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ServiceContext } from '@vtex/api'

import { getSettingsByCountry } from '../utils/getSettingsByCountry'

export function countrySettings(ctx: ServiceContext) {
  const country = ctx.vtex.route.params.country as string

  const allSettings = getSettingsByCountry(ctx.vtex.settings)

  ctx.body = allSettings[country]
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/node/middlewares/allCountrySettings.ts from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ServiceContext } from '@vtex/api'

import { getSettingsByCountry } from '../utils/getSettingsByCountry'

export function allCountrySettings(ctx: ServiceContext) {
  const allSettings = getSettingsByCountry(ctx.vtex.settings)

  ctx.body = Object.values(allSettings)
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/node/utils/getSettingsByCountry.ts from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const getSettingsByCountry = (settings: Configuration[]) => {
  const settingsByCountry = settings.reduce<{
    [country: string]: CountryDataConfiguration
  }>((groupedConfigs, configuration) => {
    const { declarer } = configuration

    const [declarerAppName] = declarer.split('@')

    if (!configuration[declarerAppName]) {
      return groupedConfigs
    }

    const countryConfig = configuration[declarerAppName]

    groupedConfigs[countryConfig.countryISO] = countryConfig

    return groupedConfigs
  }, {})

  return settingsByCountry
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/node/resolvers/country.ts from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ServiceContext } from '@vtex/api'

import { getSettingsByCountry } from '../utils/getSettingsByCountry'

export const root = {
  AdditionalFieldData: {
    __resolveType: (additionalData: any) => {
      if ('forgottenURL' in additionalData) {
        return 'PostalCodeData'
      }

      return null
    },
  },
  Field: {
    additionalData: (field: AddressFieldsConfiguration | PostalCodeField) => {
      if ('forgottenURL' in field) {
        return {
          forgottenURL: field.forgottenURL,
        }
      }

      return null
    },
  },
}

export const queries = {
  countryData: (
    _: void,
    { country }: { country: string },
    ctx: ServiceContext
  ) => {
    const data = getSettingsByCountry(ctx.vtex.settings.dependenciesSettings)[
      country
    ]

    return data
  },
  countriesData: (
    _: void,
    { countries }: { countries: string[] },
    ctx: ServiceContext
  ) => {
    return Object.values(
      getSettingsByCountry(ctx.vtex.settings.dependenciesSettings)
    ).filter(countryConfiguration =>
      countries.includes(countryConfiguration.countryISO)
    )
  },
  allCountriesData: (_: void, __: void, ctx: ServiceContext) => {
    return Object.values(
      getSettingsByCountry(ctx.vtex.settings.dependenciesSettings)
    )
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of country-data-settings/node/resolvers/index.ts from the country-data-settings VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { GraphQLJSON, GraphQLJSONObject } from 'graphql-type-json'

import { root as countryRoot, queries as countryQueries } from './country'

export default {
  JSON: GraphQLJSON,
  JSONObject: GraphQLJSONObject,
  ...countryRoot,
  Query: {
    ...countryQueries,
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of render-session/docs/README.md from the render-session VTEX app.

[Assistant]
Here's the implementation:

```markdown
# render-session
> External session provider for vtex.render-runtime

## Developing
To build run:
```
yarn && yarn clean && yarn build
```

This will build the app and generate a bundle in the `/dist` folder.

To test it, run
```
yarn && yarn start
```

this will start a webserver serving the file in the `/dist` folder.

### Testing
Set the `http:localhost:8080/index.min.js` in the render-runtime's externals and get ready for the fun :)

> If your web browser complains about CORS, be sure to add [this extension](https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en) to chrome

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of render-session/src/constants.ts from the render-session VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const ITEMS = [
  "account.id",
  "account.accountName",
  "store.channel",
  "store.countryCode",
  "store.cultureInfo",
  "store.currencyCode",
  "store.currencySymbol",
  "store.admin_cultureInfo",
  "creditControl.creditAccounts",
  "creditControl.deadlines",
  "creditControl.minimumInstallmentValue",
  "authentication.storeUserId",
  "authentication.storeUserEmail",
  "profile.firstName",
  "profile.document",
  "profile.email",
  "profile.id",
  "profile.isAuthenticated",
  "profile.lastName",
  "profile.phone",
  "public.favoritePickup",
  "public.utm_source",
  "public.utm_medium",
  "public.utm_campaign",
  "public.utmi_cp",
  "public.utmi_p",
  "public.utmi_pc",
];

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of render-session/src/index.ts from the render-session VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ITEMS } from './constants'
import { tryRefreshTokenRenew, setFirstOrRemoveRenewKey } from './refreshtoken'
import { SessionResponse } from './interfaces'

const delay = (ms: number): Promise<void> => {
  return new Promise(resolve => setTimeout(resolve, ms))
}

const bindingChanged = window.__RUNTIME__ && window.__RUNTIME__.bindingChanged
const bindingId = window.__RUNTIME__ && window.__RUNTIME__.binding && window.__RUNTIME__.binding.id
const supportedLocales = window.__RUNTIME__ && window.__RUNTIME__.culture && window.__RUNTIME__.culture.availableLocales || []
const rootPath = window.__RUNTIME__ && window.__RUNTIME__.rootPath || ''

const RETRY_STATUSES = [ 408, 425, 429, 500,  501,  502,  503,  504,  505,  506,  507,  508,  510,  511 ]
const FETCH_TIMEOUT = 7000

const canRetry = (status: number) => RETRY_STATUSES.includes(status)

const fetchWithRetry = (url: string, init: RequestInit, maxRetries: number = 3) => {
  let status = 500
  let didTimeout = false
  const callFetch = (attempt: number = 0): Promise<SessionResponse> =>
    new Promise((resolve, reject) => {
      const timeout = setTimeout(() => {
        didTimeout = true
        reject(new Error('Fetch timed out'))
      }, FETCH_TIMEOUT)
      fetch(url, init).then(response => {
        clearTimeout(timeout)
        if (!didTimeout) {
          resolve(response)
        }
      }).catch(err =>  {
        clearTimeout(timeout)
        if (didTimeout) {
          return
        }
        reject(err)
      })
    }).then((response: any) => {
      status = response.status
      return response.json()
        .then((data: any) => ({response: data, error: null}))
    }).catch((error) => {
      console.error(error)

      if (attempt >= maxRetries || !canRetry(status) || didTimeout) {
        return {response: null, error: {message: 'Maximum number of attempts achieved or request timed out'}} as SessionResponse
      }

      const ms = (2 ** attempt) * 500
      return delay(ms)
        .then(() => callFetch(++attempt))
    })

  return callFetch()
}

const patchSession = (data?: any) => fetchWithRetry(`${rootPath}/api/sessions${window.location.search}`, {
  body: data ? JSON.stringify(data) : '{}',
  credentials: 'same-origin',
  headers: new Headers({ 'Content-Type': 'application/json' }),
  method: 'PATCH',
}).catch(err => console.log('Error while patching session with error: ', err))

const supportedLocalesSearch = supportedLocales.length > 0
  ? `&supportedLocales=${supportedLocales.join(',')}`
  : ''

const bindingIdSearch = bindingId
  ? `&__bindingId=${bindingId}`
  : ''

const createInitialSessionRequest = () => {
  const items = `${window.location.search ? '&' : '?'}items=${ITEMS.join(',')}`
  return fetchWithRetry(`${rootPath}/api/sessions${window.location.search}${items}${supportedLocalesSearch}${bindingIdSearch}`, {
    body: '{}',
    credentials: 'same-origin',
    headers: new Headers({ 'Content-Type': 'application/json' }),
    method: 'POST',
  })
}

const clearSession = () => {
  return fetchWithRetry(`${rootPath}/api/sessions/invalidToken?items=*`, {
    credentials: 'same-origin',
    headers: new Headers({ 'Content-Type': 'application/json' }),
    method: 'GET',
  }, 1)
}

const onError = (err: any) => console.log('Error while loading session with error: ', err)

let sessionPromise: Promise<void | SessionResponse>

if (bindingChanged) {
  sessionPromise = tryRefreshTokenRenew()
    .then(clearSession)
    .then(createInitialSessionRequest)
    .then(setFirstOrRemoveRenewKey)
    .catch(onError);
} else {
  sessionPromise = tryRefreshTokenRenew()
    .then(createInitialSessionRequest)
    .then(setFirstOrRemoveRenewKey)
    .catch(onError);
}

(window as any).__RENDER_7_SESSION__ = (window as any).__RENDER_8_SESSION__ = {
  patchSession,
  sessionPromise,
}

export {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of render-session/src/refreshtoken.ts from the render-session VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { SessionResponse, SessionResponseData, RefreshTokenRenewResponse } from './interfaces'

const rootPath = window.__RUNTIME__ && window.__RUNTIME__.rootPath || ''
const REFRESH_TOKEN_API = `${rootPath}/api/vtexid/refreshtoken/webstore`
const LOCAL_STORAGE_KEY = 'vid_rt_webstore'
const STATUS = {
  SUCCESS: 'success',
  INVALID_SESSION: 'invalidsession',
  ERROR: 'error'
}
const TTL_30_MIN = 30 * 60 * 1000
const TTL_12_HOURS = 12 * 60 * 60 * 1000
const APPNAME = 'render-session'
const TIMEOUT = 2000

const setItem = (status: string, refreshAfter: Date) =>
  localStorage.setItem(
    LOCAL_STORAGE_KEY,
    JSON.stringify({ status, refreshAfter })
  )

const removeKey = () => {
  localStorage.removeItem(LOCAL_STORAGE_KEY)
}

const setError = () =>
  setItem(STATUS.ERROR, new Date(new Date().getTime() + TTL_30_MIN))

const fetchWithTimeout = (url: string, options: RequestInit | undefined, timeout: number): Promise<Response> => {
  return new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error("timeout")), timeout)
    fetch(url, options).then(resolve, reject)
  })
}

export const setFirstOrRemoveRenewKey = (sessionResponse: SessionResponse) => {
  try {
    const localStorage = window.localStorage
    if (!localStorage) return

    const profile = (sessionResponse.response as SessionResponseData).namespaces.profile;
    const isAuthenticated = profile && profile.isAuthenticated.value === "true"
    const keyExists = localStorage.getItem(LOCAL_STORAGE_KEY)

    if (isAuthenticated && !keyExists) {
      setItem(STATUS.SUCCESS, new Date(new Date().getTime() + TTL_12_HOURS))
    }
    if (!isAuthenticated && keyExists) {
      removeKey()
    }
  }
  finally {
    return sessionResponse
  }
}

export const tryRefreshTokenRenew = async () => {
  const localStorage = window.localStorage
  if (!localStorage) return

  try {
    const now = new Date()

    const curr = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY) || 'null')
    if (!curr || now < new Date(curr.refreshAfter)) return

    const response = await fetchWithTimeout(REFRESH_TOKEN_API, {
      method: 'POST',
      headers: {
        'vtex-id-ui-version': APPNAME,
        'content-type': 'application/json'
      },
      body: '{}',
    }, TIMEOUT)

    const data: RefreshTokenRenewResponse = await response.json();

    if (!data || !data.status) {
      setError()
      return
    }

    const status = data.status.toLowerCase()

    if (status === STATUS.INVALID_SESSION) {
      removeKey()
      return
    }

    if (status === STATUS.SUCCESS) {
      const { refreshAfter } = data
      setItem(status, new Date(refreshAfter as string))
      return
    }

    setError()
  } catch {
    setError()
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of render-session/src/interfaces.ts from the render-session VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare global {
  export interface Window {
    __RUNTIME__: {
      binding?: {
        id: string
      },
      bindingChanged?: boolean,
      culture: {
        availableLocales: string[]
      }
      rootPath?: string
    }
  }
}

export interface SessionResponse {
  response: SessionResponseData | null,
  error: any,
}

export interface SessionResponseData {
  namespaces: {
    profile: {
      isAuthenticated: {
        value: string
      }
    }
  }
}

export interface RefreshTokenRenewResponse {
  status: string,
  userId: string | null,
  refreshAfter: string | null,
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of external-promotions-example/docs/README.md from the external-promotions-example VTEX app.

[Assistant]
Here's the implementation:

```markdown
# External Promotions Example

This app is an example to merchants on how to implment their own external promotions customization backend apps. It should expose an API that will recceive the context that is needed to calculate the external promotions on 3rd-party providers, transform this data to the expected contract defined by VTEX and call the VTEX's internal app responsible for applying the external promotions.

Here is what we expect to be the context on each supported scenario:

| Scenario | Context                                                                                |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| PDP      | The details of the item in display, such as the sku id, original seling price, etc, alongside with the shopper's session.                                                                                |
| PLP      | The details of items in the search result, similarly to the PDP scenario, but for multiple independent items, alongside with the shopper's session. Please beware that this is not a shopping cart with multiple items, but a collection of independent items. |
| Checkout | WIP                                                                                |

## API

Here we'll give an overview of how this API should be implemented by the merchants.

### Calculate External Promotions endpoint

This is a public method that will be called by the storefront customizations and it's responsible for making a request to the 3rd-party external provider and send this data to the VTEX platform, respecting the defined protocol. This app is agnostic from the store's implementation, meaning that we don't see a reason why it shouldn't work in all current store frameworks supported by VTEX (Portal, SF, and FastStore). However, from a product perspective, we'll foment the usage of our latest technologies and suggest using FastStore for your store's implementation.

**Overview**

| Property             | Value                            |
| -------------------- | -------------------------------- |
| Method               | `POST`                           |
| URL                  | `/promotions/external/calculate` |
| Auth required        | No                               |
| Permissions required | None                             |
| Request body         | `application/json`               |
| Response             | `application/json`               |

**Request body**
| Property | Type | Required | Description |
|---------------------- |------------------------- | ---------- | ---------- |
| sessionId | string | yes | The id of the shopper's active session. |
| promotionalContext | PromotionalContext | yes | The context that should be used for calculating the external promotions. This data is completely customizable and its format is entirely up to the merchant. For the example we'll use a simple array of items with its' sku ids and original prices. |

**PromotionalContext**
| Property | Type | Required | Description |
|---------------------- |------------------------- | ---------- | ---------- |
| items | Item[] | yes | An array of product items that will be used for calculating the external promotions. |

**Item**
| Property | Type | Required | Description |
|---------------------- |------------------------- | ---------- | ---------- |
| id | string | yes | The unique identifier for the item, aka SKU ID. |
| sellingPrice | number | yes | The original selling price of the item. By original we mean that we expect this to be the selling price of the item before any discounts are applied |

**Request body example**

Provide name of Account to be created.

```json
{
  "sessionId": "session_id",
  "promotionalContext": {
    "items": [
      {
        "id": "1",
        "sellingPrice": 1000
      }
    ]
  }
}
```

**VTEX External Promotions data contract**

| Property   | Type           | Required                   | Description                                                                                |
| ---------- | -------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| version    | "v1"           | yes                        | The version of the data contract.                                                                                |
| type       | "page", "cart" | yes                        | The type of the data contract. <br> "page" means that the data being sent is valid for page contexts (PDP/PLP). <br> "cart" means that the data being sent is valid to art contexts (Checkout). |
| exp        | number         | no                         | The unix time (milliseconds) until the sent data becomes invalid.                                                                                |
| cartHash   | string         | yes (for "cart" type only) | A hash key for the cart in which this promotions data is valid for. This will be used for matching the promotional data when navigating to chekout and when placing the order.                  |
| sessionId  | string         | yes                        | An unique identifier of the shopper's active session in which the promotional data is valid.                                                                                |
| promotions | Promotion[]    | yes                        | An array of valid promotions that need to be applied for the specified context.                                                                                |

**Promotion**
| Property | Type |Required | Description |
|---------------------- | ------------------------- |-------- | ---------- |
| identifier | string | yes | An identifier for the promotion. |
| effect | Effect | yes | The discount definition that will be applied. |
| scope | Scope[] | yes | The definition of on which items the discount should be applied. |

**Effect**
| Property | Type |Required | Description |
|---------------------- |------------------------- |-------- | ---------- |
| type | "nominal" | yes | The type of discount that is being given. |
| settings | Settings | yes | The definition of the discount itself to be applied. |

**Settings**
| Property | Type |Required | Description |
|---------------------- |------------------------- |-------- | ---------- |
| value | number | yes | The amount/value of the discount |
| applyMode | "OnEachItem", "SharedAmongItems" | yes | How the discount will be appliend on the items described in the scope. <br> "OnEachItem" means that the whole amount will be applied to all matching items. <br> "SharedAmongItems" means that the amount will be split and shared evenly among the matching items. |

**Scope**
| Property | Type | Required | Description |
|---------------------- |------------------------- | -------- | ---------- |
| skuId | string | yes |The unique identifier of the item on which the disount should be applied. |
| quantity | number | yes | The quantity of same items on which the discount should be applied. |

For more information see the External Promotion Fields Explanation on this [RFC](https://docs.google.com/document/d/1BPkfRz3t2BENqZaVMwToDALK5ePRoDWAlHoyD2qM5WU/edit#heading=h.1kydlntegy7j).

**Response example**

```json
{
  "version": "v1",
  "type": "page",
  "exp": 1680812032408,
  "cartHash": "cart_hash",
  "sessionId": "session_id",
  "promotions": [
    {
      "identifier": "mocked-external-promotion",
      "effect": {
        "type": "nominal",
        "settings": {
          "value": 90,
          "applyMode": "OnEachItem"
        }
      },
      "scope": [
        {
          "skuId": "1",
          "quantity": 1
        }
      ]
    }
  ]
}
```

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of external-promotions-example/node/service.json from the external-promotions-example VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "memory": 256,
  "ttl": 10,
  "timeout": 300,
  "minReplicas": 2,
  "maxReplicas": 4,
  "workers": 1,
  "routes": {
    "calculateExternalPromotions": {
      "path": "/_v/promotions/external/calculate",
      "public": true
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of external-promotions-example/node/package.json from the external-promotions-example VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "dependencies": {
    "co-body": "^6.0.0",
    "ramda": "^0.25.0"
  },
  "devDependencies": {
    "@types/co-body": "^0.0.3",
    "@types/jest": "^24.0.18",
    "@types/node": "^12.0.0",
    "@types/ramda": "types/npm-ramda#dist",
    "@vtex/api": "6.45.15",
    "@vtex/test-tools": "^1.0.0",
    "@vtex/tsconfig": "^0.5.6",
    "typescript": "3.9.7"
  },
  "resolutions": {
    "@types/testing-library__dom": "6.12.1",
    "@types/express": "4.16.0",
    "@types/express-serve-static-core": "4.16.0"
  },
  "scripts": {
    "lint": "tsc --noEmit --pretty"
  },
  "version": "0.2.21"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of external-promotions-example/node/index.ts from the external-promotions-example VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ClientsConfig, ServiceContext, RecorderState } from '@vtex/api'
import { method, Service } from '@vtex/api'

import { Clients } from './clients'
import { calculate } from './middlewares/promotions/external/calculate'

const TIMEOUT_MS = 2000

// This is the configuration for clients available in `ctx.clients`.
const clients: ClientsConfig<Clients> = {
  // We pass our custom implementation of the clients bag, containing the Status client.
  implementation: Clients,
  options: {
    // All IO Clients will be initialized with these options, unless otherwise specified.
    default: {
      retries: 2,
      timeout: TIMEOUT_MS,
    },
  },
}

declare global {
  // We declare a global Context type just to avoid re-writing ServiceContext<Clients, State> in every handler and resolver
  type Context = ServiceContext<Clients, State>

  // The shape of our State object found in `ctx.state`. This is used as state bag to communicate between middlewares.
  interface State extends RecorderState {
    code: number
  }
}

// Export a service that defines route handlers and client options.
export default new Service({
  clients,
  routes: {
    // `status` is the route ID from service.json. It maps to an array of middlewares (or a single handler).
    calculateExternalPromotions: method({
      POST: [calculate],
    }),
  },
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of external-promotions-example/node/clients/vtex-external-promotions-app.ts from the external-promotions-example VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { InstanceOptions, IOContext } from '@vtex/api'
import { AppClient } from '@vtex/api'

export interface VTEXExternalPromotionsDataContract {
  items: Item[]
  sessionId: string
  externalPromotions: ExternalPromotion[]
}

interface Item {
  id: string
  quantity: number
  seller: string
}

interface ExternalPromotion {
  version: DataContractVersion
  exp: number
  type: DataContractType
  cartHash?: string
  promotions: Promotion[]
}

export const enum DataContractVersion {
  v1 = 'v1',
}

export const enum DataContractType {
  cart = 'cart',
  page = 'page',
}

export interface Promotion {
  identifier: string
  effect: PromotionEffect
  scope: PromotionScope[]
}

interface PromotionEffect {
  type: string
  settings: PromotionEffectSettings
}

interface PromotionEffectSettings {
  value: number
  applyMode: PromotionEffectSettingsApplyMode
}

const enum PromotionEffectSettingsApplyMode {
  onEachItem = 'OnEachItem',
  sharedAmongItems = 'SharedAmongItems',
}

interface PromotionScope {
  skuId: string
  quantity: number
}

export type ApplyPromotionsResponse = Record<string, unknown>

export class VTEXExternalPromotionsApp extends AppClient {
  constructor(context: IOContext, options?: InstanceOptions) {
    super('vtex.external-promotions-middleware@0.x', context, options)
  }

  public applyExternalPromotions(data: VTEXExternalPromotionsDataContract) {
    // this may change when we implment the app on VTEX's side
    return this.http.post<ApplyPromotionsResponse>(
      '/_v/promotions/external/apply/page',
      data,
      {
        metric: 'apply-external-promotions',
      }
    )
  }
}

```