'use strict'
/**
* @author Ian Harisay
*/
/**
* @typedef {Object} MexicoState
* @property {String} name Name of the federative entity
* @property {Array<String>} abbreviation Conventional abbreviations
* @property {String} internal internal Nu Skin name
* @property {String} iso2 2-letter ISO code
* @property {String} iso3 3-letter ISO code
* @example
*
* {
* name: 'Michoacán',
* abbreviation: ['Mich.'],
* internal: 'MIC',
* iso2: 'MI',
* iso3: 'MIC'
* }
*/
const { isString } = require('@nuskin/uncle-buck')
// state data taken from https://en.wikipedia.org/wiki/Template:Mexico_State-Abbreviation_Codes
const states = [
{ name: 'Aguascalientes', abbreviation: ['Ags.'], iso2: 'AG', iso3: 'AGU', internal: 'AGU' },
{ name: 'Baja California', abbreviation: ['B.C.'], iso2: 'BC', iso3: 'BCN', internal: 'BCN' },
{ name: 'Baja California Sur', abbreviation: ['B.C.S.'], iso2: 'BS', iso3: 'BCS', internal: 'BCS' },
{ name: 'Campeche', abbreviation: ['Camp.'], iso2: 'CM', iso3: 'CAM', internal: 'CAM' },
{ name: 'Chiapas', abbreviation: ['Chis.'], iso2: 'CS', iso3: 'CHP', internal: 'CHI' }, // different
{ name: 'Chihuahua', abbreviation: ['Chih.'], iso2: 'CH', iso3: 'CHH', internal: 'CHH' },
{ name: 'Coahuila', abbreviation: ['Coah.'], iso2: 'CO', iso3: 'COA', internal: 'COA' },
{ name: 'Colima', abbreviation: ['Col.'], iso2: 'CL', iso3: 'COL', internal: 'COL' },
{ name: 'Mexico City', abbreviation: ['CDMX'], iso2: 'DF', iso3: 'CMX', internal: 'CMX' },
{ name: 'Durango', abbreviation: ['Dgo.'], iso2: 'DG', iso3: 'DUR', internal: 'DUR' },
{ name: 'Guanajuato', abbreviation: ['Gto.'], iso2: 'GT', iso3: 'GUA', internal: 'GUA' },
{ name: 'Guerrero', abbreviation: ['Gro.'], iso2: 'GR', iso3: 'GRO', internal: 'GUE' }, // different
{ name: 'Hidalgo', abbreviation: ['Hgo.'], iso2: 'HG', iso3: 'HID', internal: 'HID' },
{ name: 'Jalisco', abbreviation: ['Jal.'], iso2: 'JA', iso3: 'JAL', internal: 'JAL' },
{ name: 'México', abbreviation: ['Méx.'], iso2: 'EM', iso3: 'MEX', internal: 'MEX' },
{ name: 'Michoacán', abbreviation: ['Mich.'], iso2: 'MI', iso3: 'MIC', internal: 'MIC' },
{ name: 'Morelos', abbreviation: ['Mor.'], iso2: 'MO', iso3: 'MOR', internal: 'MOR' },
{ name: 'Nayarit', abbreviation: ['Nay.'], iso2: 'NA', iso3: 'NAY', internal: 'NAY' },
{ name: 'Nuevo León', abbreviation: ['N.L.'], iso2: 'NL', iso3: 'NLE', internal: 'NL' }, // different
{ name: 'Oaxaca', abbreviation: ['Oax.'], iso2: 'OA', iso3: 'OAX', internal: 'OAX' },
{ name: 'Puebla', abbreviation: ['Pue.'], iso2: 'PU', iso3: 'PUE', internal: 'PUE' },
{ name: 'Querétaro', abbreviation: ['Qro.'], iso2: 'QT', iso3: 'QUE', internal: 'QUE' },
{ name: 'Quintana Roo', abbreviation: ['Q. Roo.','Q.R.'], iso2: 'QR', iso3: 'ROO', internal: 'QR' }, // different
{ name: 'San Luis Potosí', abbreviation: ['S.L.P.'], iso2: 'SL', iso3: 'SLP', internal: 'SLP' },
{ name: 'Sinaloa', abbreviation: ['Sin.'], iso2: 'SI', iso3: 'SIN', internal: 'SIN' },
{ name: 'Sonora', abbreviation: ['Son.'], iso2: 'SO', iso3: 'SON', internal: 'SON' },
{ name: 'Tabasco', abbreviation: ['Tab.'], iso2: 'TB', iso3: 'TAB', internal: 'TAB' },
{ name: 'Tamaulipas', abbreviation: ['Tamps.'], iso2: 'TM', iso3: 'TAM', internal: 'TAM' },
{ name: 'Tlaxcala', abbreviation: ['Tlax.'], iso2: 'TL', iso3: 'TLA', internal: 'TLA' },
{ name: 'Veracruz', abbreviation: ['Ver.'], iso2: 'VE', iso3: 'VER', internal: 'VER' },
{ name: 'Yucatán', abbreviation: ['Yuc.'], iso2: 'YU', iso3: 'YUC', internal: 'YUC' },
{ name: 'Zacatecas', abbreviation: ['Zac.'], iso2: 'ZA', iso3: 'ZAC', internal: 'ZAC' }
]
/**
* _removeDiacritics replaces accents/diacritics for the ASCII character
* @ignore
* @param {String} str string to replace accents
* @returns {String} replacement string
*/
const _removeDiacritics = (str) => {
return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "")
}
/**
* @ignore
* @param {String} str The string to strip characters and diacritics from
* @returns {String} Stripped down string
*/
const _strip = (str) => {
if(isString(str)){
str = _removeDiacritics(str)
.replace(/[.]/g, '')
.replace(/\s{2,}/g, ' ')
.replace(/(^\s+|\s+$)/g, '')
.toLowerCase()
}
return str
}
/**
* _search searches for the code states data based on the field provided
* @ignore
* @param {Srting} field field to search for the code in. field can be:
* name, abbreviation, iso
* @param {String} code
* @returns {MexicoState} Returns a `MexicoState` object if one is found. Else
* an empty `Object` is returned.
*/
const _search = (field, code) => {
let rv = {}
OUTER: for(let state of states){
if(Array.isArray(state[field])){
for(let ele of state[field]){
if (_strip(ele) === _strip(code)) {
rv = state
break OUTER
}
}
} else if (_strip(state[field]) === _strip(code)) {
rv = state
break
}
}
return rv
}
/**
* byAbbr will search Mexico states by the conventional abbreviation
* @memberof Utility.MexicoStateLookup
* @param {String} abbr The conventional abbreviation to search by.
* @returns {MexicoState} Returns a `MexicoState` object if one is found. Else
* an empty `Object` is returned.
* @example
* const msc = require('@nuskin/mexico-state-lookup')
*
* // How to lookup 'Nuevo León' by abbreviation
* const state = msc.byAbbr('N.L.')
*/
const byAbbr = (abbr) => {
return _search('abbreviation', abbr)
}
/**
* byInternal will search Mexico states by Nu Skin's internal name.
* @param {String} internalName The internal name to search by.
* @returns {MexicoState} Returns a `MexicoState` object if one is found. Else
* an empty `Object` is returned.
* @example
* const msc = require('@nuskin/mexico-state-lookup')
*
* // How to lookup 'Nuevo León' by iso code
* const state = msc.byIso('NL') // or 'NLE'
*/
const byInternal = (internalName) => {
return _search('internal', internalName)
}
/**
* byIso will search Mexico states by ISO2 or ISO3 codes
* @param {String} code The iso code to search by.
* @returns {MexicoState} Returns a `MexicoState` object if one is found. Else
* an empty `Object` is returned.
* @example
* const msc = require('@nuskin/mexico-state-lookup')
*
* // How to lookup 'Nuevo León' by iso code
* const state = msc.byIso('NL') // or 'NLE'
*/
const byIso = (code) => {
let rv = {}
if (code.length === 2) {
rv = _search('iso2', code.toUpperCase())
}
if (code.length === 3) {
rv = _search('iso3', code.toUpperCase())
}
return rv
}
/**
* byName will search Mexico states by the state name
* @param {String} name The federative name to search for.
* @returns {MexicoState} Returns a `MexicoState` object if one is found. Else
* an empty `Object` is returned.
* @example
* const msc = require('@nuskin/mexico-state-lookup')
*
* // How to lookup 'Nuevo León' by name
* const state = msc.byName('Nuevo León')
*/
const byName = (name) => {
return _search('name', name)
}
/**
* byAll searches byAbbr, byInternal, byIso, and byName for a match of the given string
* @param {String} str The string to search by.
* @returns {MexicoState} Returns a `MexicoState` object if one is found. Else
* an empty `Object` is returned.
* @example
* const msc = require('@nuskin/mexico-state-lookup')
*
* // How to find the state by any attribute
* const state = msc.byAll('Nuevo León')
*/
const byAll = (str) => {
let rv = {}
if(Object.keys(byAbbr(str)).length){
rv = byAbbr(str)
} else if(Object.keys(byIso(str)).length){
rv = byIso(str)
} else if(Object.keys(byName(str)).length){
rv = byName(str)
} else if(Object.keys(byInternal(str)).length){
rv = byInternal(str)
}
return rv
}
/**
* getStates returns a list of all the Mexico states.
* @returns {Array<MexicoState>} Returns a list of all the Mexico states
* @example
* const msc = require('@nuskin/mexico-state-lookup')
*
* const states = msc.getStates()
* states.forEach(state => {
* console.log({state})
* })
*/
const getStates = () => {
return JSON.parse(JSON.stringify(states))
}
module.exports = {
byAll,
byAbbr,
byInternal,
byIso,
byName,
getStates
}