Skip to content
Snippets Groups Projects
insee.js 1.89 KiB
Newer Older
  • Learn to ignore specific revisions
  • Bastien DUMONT's avatar
    Bastien DUMONT committed
    // @ts-check
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    const Sentry = require('@sentry/node')
    
    const { default: axios } = require('axios')
    
    const { log, errors } = require('cozy-konnector-libs')
    
    const API_URL = 'https://apicarto.ign.fr/api/codes-postaux/communes'
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    /**
     * Return inseeCode given a postalCode
     * @param {string} postalCode
    
     * @param {string} [city]
    
     * @return {Promise<string>} inseeCode
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
     */
    
    async function getInseeCode(postalCode, city) {
      try {
        log('info', `Query getInseeCode for postalCode ${postalCode} / ${city}`)
        const response = await axios.get(`${API_URL}/${postalCode}`)
    
        if (response.data.length === 1) {
          return response.data[0].codeCommune
        } else {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
          if (!city) throw new Error('No city')
    
          const parsedCity = sanitizeCity(city)
    
    
          const filteredResponse = response.data.filter(commune =>
            sanitizeCity(commune.nomCommune).includes(parsedCity)
    
          if (filteredResponse.length > 1) {
            throw new Error(
              'Input city is not precise enough, more than one city was found'
            )
          }
    
    
          return filteredResponse[0].codeCommune
        }
      } catch (error) {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
        const errorMessage = `Query getInseeCode failed for postalCode ${postalCode} / ${city}`
        log('error', errorMessage)
        Sentry.captureException(errorMessage)
    
        throw errors.USER_ACTION_NEEDED
    
    /**
     * Clean city input and remove all characters such as (^, ¨, ʼ, ', -, é, è)
     * @param {string} city
     * @return {string} parsedCity
     */
    function sanitizeCity(city) {
      return city
        .toLowerCase()
    
        .replace(/\bst\b/i, 'saint')
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
        .replace(/[âêîôûäëïöü-\sʼ'’éàèç]/g, match => REPLACE_CHARS[match])
    
        .trim()
    }
    
    const REPLACE_CHARS = {
      â: 'a',
      ê: 'e',
      î: 'i',
      ô: 'o',
      û: 'u',
      ä: 'a',
      ë: 'e',
      ï: 'i',
      ö: 'o',
      ü: 'u',
      '-': '',
      ' ': '',
      ʼ: '',
      "'": '',
    
      '': '',
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      à: 'a',
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    module.exports = {
      getInseeCode,
    }