@pretto/places 0.3.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # @pretto/places
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@pretto/places.svg?style=flat)](https://www.npmjs.com/package/@pretto/places)
4
+
5
+ Allows you to search for an address, a postcode or a French department.
6
+ You can also search a country.
7
+
8
+ ## FAQ
9
+
10
+ ### How to implement the library?
11
+
12
+ ```sh
13
+ yarn add @pretto/places
14
+ ```
15
+
16
+ For municipality and zipcode
17
+
18
+ ```jsx
19
+ import { municipalitySearch } from '@pretto/places'
20
+
21
+ const result = await municipalitySearch.get("paris", { limit: 21 })
22
+
23
+ // expected result : Paris (75001), Paris (75002), Paris (75003), ..., Paris (75020)
24
+ // result object format :
25
+ [
26
+ {
27
+ "label": "Paris (75001)",
28
+ "value": {
29
+ "city": "Paris",
30
+ "country": "fr",
31
+ "zipcode": "75001"
32
+ }
33
+ },
34
+ {
35
+ "label": "Paris (75002)",
36
+ "value": {
37
+ "city": "Paris",
38
+ "country": "fr",
39
+ "zipcode": "75002"
40
+ }
41
+ },
42
+ ...
43
+ ]
44
+ ```
45
+
46
+ For department only
47
+
48
+ ```jsx
49
+ import { municipalitySearch } from '@pretto/places'
50
+
51
+ const result = await municipalitySearch.get("paris", { departmentOnly: true, limit: 21 })
52
+
53
+ // expected result : Paris (75), Parisot(81), Parisot (82), Cormeilles-en-Parisis (95), ...
54
+ // result object format :
55
+ [
56
+ {
57
+ "label": "Paris (75)",
58
+ "value": {
59
+ "city": "Paris",
60
+ "country": "fr",
61
+ "zipcode": "75"
62
+ }
63
+ },
64
+ {
65
+ "label": "Parisot (81)",
66
+ "value": {
67
+ "city": "Parisot",
68
+ "country": "fr",
69
+ "zipcode": "81"
70
+ }
71
+ },
72
+ ...
73
+ ]
74
+ ```
75
+
76
+ For Address (France only)
77
+
78
+ ```jsx
79
+ import { addressSearch } from '@pretto/places'
80
+
81
+ const result = await addressSearch.get("55 rue de paradis", { limit: 10 })
82
+
83
+ // expected result : 55 Rue de Paradis 75010 Paris (75010), 55 Rue de Paradis 51160 Hautvillers (51160)...
84
+ // result object format :
85
+ [
86
+ {
87
+ "label": "55 Rue de Paradis 75010 Paris (75010)",
88
+ "value": {
89
+ "city": "Paris",
90
+ "country": "fr",
91
+ "street": "55 Rue de Paradis",
92
+ "zipcode": "75010"
93
+ }
94
+ },
95
+ {
96
+ "label": "55 Rue de Paradis 51160 Hautvillers (51160)",
97
+ "value": {
98
+ "city": "Hautvillers",
99
+ "country": "fr",
100
+ "street": "55 Rue de Paradis",
101
+ "zipcode": "51160"
102
+ }
103
+ },
104
+ ...
105
+ ]
106
+ ```
107
+
108
+ For country
109
+
110
+ ```jsx
111
+ import { countrySearch } from '@pretto/places'
112
+
113
+ const countriesApi = countrySearch.init(ALGOLIA_COUNTRIES_APP_ID, ALGOLIA_COUNTRIES_API_KEY)
114
+ const results = await countriesApi.get("al", { limit: 10 })
115
+
116
+ // expected result : Allemagne (99109), Albanie (99125), Algerie (99352)
117
+ // result object format :
118
+ [
119
+ {
120
+ "label": "Allemagne (99109)",
121
+ "value": "de"
122
+ },
123
+ {
124
+ "label": "Albanie (99125)",
125
+ "value": "al"
126
+ },
127
+ {
128
+ "label": "Algerie (99352)",
129
+ "value": "dz"
130
+ }
131
+ ]
132
+ ```
133
+
134
+ ### How to publish a new version?
135
+
136
+ When a branch is merged into master, it will automatically deploy a new version to npm.
137
+
138
+ ### How that works?
139
+
140
+ This library is based on the API of data.gouv.
141
+ These data are quite precise and are regularly updated:
142
+ ![title](https://adresse.data.gouv.fr/_next/image?url=%2Fimages%2Fdonnees-nationales%2Fschema-donnees-ban.svg&w=1080&q=75)
143
+
144
+ - https://adresse.data.gouv.fr/
145
+ - https://api.gouv.fr/
package/dist/index.js CHANGED
@@ -46,14 +46,14 @@ const convertFirstLetterToUpperCase = (str) => {
46
46
  return acc + curr;
47
47
  }, '');
48
48
  };
49
- const getUri = (search, limit) => {
49
+ const getUri = (search, departmentOnly) => {
50
50
  const PLACES_API = 'https://geo.api.gouv.fr';
51
- const QUERY_FIELDS = 'fields=departement,codesPostaux&boost=population';
51
+ const QUERY_FIELDS = `boost=population&fields=departement${departmentOnly ? '' : ',codesPostaux'}`;
52
52
  const formatedSearch = encodeURIComponent(search);
53
53
  const uri = {
54
- departments: `${PLACES_API}/departements/${formatedSearch}/communes?${QUERY_FIELDS}&limit=${limit}`,
55
- municipality: `${PLACES_API}/communes?nom=${formatedSearch}&${QUERY_FIELDS}&limit=${limit}`,
56
- zipcode: `${PLACES_API}/communes?codePostal=${formatedSearch}&${QUERY_FIELDS}&limit=${limit}`,
54
+ departments: `${PLACES_API}/departements/${formatedSearch}/communes?${QUERY_FIELDS}`,
55
+ municipality: `${PLACES_API}/communes?nom=${formatedSearch}&${QUERY_FIELDS}`,
56
+ zipcode: `${PLACES_API}/communes?codePostal=${formatedSearch}&${QUERY_FIELDS}`,
57
57
  };
58
58
  if (isNaN(parseInt(search, 10)))
59
59
  return uri.municipality;
@@ -63,43 +63,67 @@ const getUri = (search, limit) => {
63
63
  let PREVIOUS_SEARCH = [];
64
64
  let SEARCH_CACHE = [];
65
65
  let PREVIOUS_VALUE = '';
66
- const responseFormat = (places, country, search) => {
66
+ const responseFormat = (places, country, search, departmentOnly) => {
67
67
  if (places.length === 0 || !places)
68
68
  return [];
69
+ if (departmentOnly) {
70
+ return places.map(place => {
71
+ var _a, _b;
72
+ return {
73
+ label: `${place.nom}${!!((_a = place.departement) === null || _a === void 0 ? void 0 : _a.code) ? ` (${place.departement.code})` : ''}`,
74
+ value: {
75
+ city: place.nom,
76
+ country,
77
+ zipcode: ((_b = place.departement) === null || _b === void 0 ? void 0 : _b.code) || '',
78
+ },
79
+ };
80
+ });
81
+ }
69
82
  if (!isNaN(parseInt(search, 10)) && search.length === 5 && places.length === 1) {
70
- return [{ label: `${places[0].nom} (${search})`, value: { city: places[0].nom, country, zipcode: search } }];
83
+ return [
84
+ {
85
+ label: `${places[0].nom} (${search})`,
86
+ value: { city: places[0].nom, country, zipcode: search },
87
+ },
88
+ ];
71
89
  }
72
90
  const allPlaces = places.map(place => {
73
91
  return place.codesPostaux.reduce((acc, curr) => {
74
- return [...acc, { label: `${place.nom} (${curr})`, value: { city: place.nom, country, zipcode: curr } }];
92
+ return [
93
+ ...acc,
94
+ {
95
+ label: `${place.nom} (${curr})`,
96
+ value: { city: place.nom, country, zipcode: curr },
97
+ },
98
+ ];
75
99
  }, []);
76
100
  });
77
101
  return flat__default["default"](allPlaces);
78
102
  };
79
103
  const get$2 = (search, options) => __awaiter(void 0, void 0, void 0, function* () {
104
+ const { country = 'fr', limit = 5, departmentOnly = false } = options || {};
80
105
  const isNumber = !isNaN(parseInt(search, 10));
81
106
  if (!search || (isNumber && search.length < 2))
82
107
  return [];
83
108
  if (isNumber && search.length > 2 && search.length < 5 && SEARCH_CACHE.length > 0) {
84
- return SEARCH_CACHE.filter(i => i.value.zipcode.includes(search));
109
+ return SEARCH_CACHE.filter(i => i.value.zipcode.includes(search)).slice(0, limit);
85
110
  }
86
111
  try {
87
- const { country = 'fr', limit = 5 } = options || {};
88
- const response = yield fetch(getUri(search, limit));
112
+ const response = yield fetch(getUri(search, departmentOnly));
89
113
  if (!response.ok)
90
114
  return Promise.reject(response);
91
115
  const result = yield response.json();
92
- const formatedResponse = responseFormat(result, country, search);
116
+ const formatedResponse = responseFormat(result, country, search, departmentOnly);
93
117
  if (isEqual__default["default"](PREVIOUS_SEARCH, formatedResponse)) {
94
118
  const cleanValue = search.replace(' ', '').replace(PREVIOUS_VALUE, '');
95
- return PREVIOUS_SEARCH.filter(i => i.label.includes(cleanValue));
119
+ return PREVIOUS_SEARCH.filter(i => i.label.includes(cleanValue)).slice(0, limit);
96
120
  }
97
121
  PREVIOUS_VALUE = search;
98
122
  PREVIOUS_SEARCH = formatedResponse;
99
123
  if (isNumber && search.length !== 5) {
100
124
  SEARCH_CACHE = formatedResponse;
101
125
  }
102
- return formatedResponse;
126
+ return formatedResponse.slice(0, limit);
103
127
  }
104
128
  catch (error) {
105
129
  if (typeof error === 'string')
@@ -162,7 +186,7 @@ const get = (instance, search, options) => __awaiter(void 0, void 0, void 0, fun
162
186
  if (codeiso2 === '')
163
187
  return acc;
164
188
  const formatCountryName = convertFirstLetterToUpperCase(libcog.includes('(') ? libenr : libcog);
165
- const formatCog = cog.includes('X') ? `(${cog})` : '';
189
+ const formatCog = !cog.includes('X') ? `(${cog})` : '';
166
190
  const label = `${formatCountryName} ${formatCog}`;
167
191
  return [...acc, { label, value: codeiso2.toLowerCase() }];
168
192
  }, []);
package/dist/module.js CHANGED
@@ -36,14 +36,14 @@ const convertFirstLetterToUpperCase = (str) => {
36
36
  return acc + curr;
37
37
  }, '');
38
38
  };
39
- const getUri = (search, limit) => {
39
+ const getUri = (search, departmentOnly) => {
40
40
  const PLACES_API = 'https://geo.api.gouv.fr';
41
- const QUERY_FIELDS = 'fields=departement,codesPostaux&boost=population';
41
+ const QUERY_FIELDS = `boost=population&fields=departement${departmentOnly ? '' : ',codesPostaux'}`;
42
42
  const formatedSearch = encodeURIComponent(search);
43
43
  const uri = {
44
- departments: `${PLACES_API}/departements/${formatedSearch}/communes?${QUERY_FIELDS}&limit=${limit}`,
45
- municipality: `${PLACES_API}/communes?nom=${formatedSearch}&${QUERY_FIELDS}&limit=${limit}`,
46
- zipcode: `${PLACES_API}/communes?codePostal=${formatedSearch}&${QUERY_FIELDS}&limit=${limit}`,
44
+ departments: `${PLACES_API}/departements/${formatedSearch}/communes?${QUERY_FIELDS}`,
45
+ municipality: `${PLACES_API}/communes?nom=${formatedSearch}&${QUERY_FIELDS}`,
46
+ zipcode: `${PLACES_API}/communes?codePostal=${formatedSearch}&${QUERY_FIELDS}`,
47
47
  };
48
48
  if (isNaN(parseInt(search, 10)))
49
49
  return uri.municipality;
@@ -53,43 +53,67 @@ const getUri = (search, limit) => {
53
53
  let PREVIOUS_SEARCH = [];
54
54
  let SEARCH_CACHE = [];
55
55
  let PREVIOUS_VALUE = '';
56
- const responseFormat = (places, country, search) => {
56
+ const responseFormat = (places, country, search, departmentOnly) => {
57
57
  if (places.length === 0 || !places)
58
58
  return [];
59
+ if (departmentOnly) {
60
+ return places.map(place => {
61
+ var _a, _b;
62
+ return {
63
+ label: `${place.nom}${!!((_a = place.departement) === null || _a === void 0 ? void 0 : _a.code) ? ` (${place.departement.code})` : ''}`,
64
+ value: {
65
+ city: place.nom,
66
+ country,
67
+ zipcode: ((_b = place.departement) === null || _b === void 0 ? void 0 : _b.code) || '',
68
+ },
69
+ };
70
+ });
71
+ }
59
72
  if (!isNaN(parseInt(search, 10)) && search.length === 5 && places.length === 1) {
60
- return [{ label: `${places[0].nom} (${search})`, value: { city: places[0].nom, country, zipcode: search } }];
73
+ return [
74
+ {
75
+ label: `${places[0].nom} (${search})`,
76
+ value: { city: places[0].nom, country, zipcode: search },
77
+ },
78
+ ];
61
79
  }
62
80
  const allPlaces = places.map(place => {
63
81
  return place.codesPostaux.reduce((acc, curr) => {
64
- return [...acc, { label: `${place.nom} (${curr})`, value: { city: place.nom, country, zipcode: curr } }];
82
+ return [
83
+ ...acc,
84
+ {
85
+ label: `${place.nom} (${curr})`,
86
+ value: { city: place.nom, country, zipcode: curr },
87
+ },
88
+ ];
65
89
  }, []);
66
90
  });
67
91
  return flat(allPlaces);
68
92
  };
69
93
  const get$2 = (search, options) => __awaiter(void 0, void 0, void 0, function* () {
94
+ const { country = 'fr', limit = 5, departmentOnly = false } = options || {};
70
95
  const isNumber = !isNaN(parseInt(search, 10));
71
96
  if (!search || (isNumber && search.length < 2))
72
97
  return [];
73
98
  if (isNumber && search.length > 2 && search.length < 5 && SEARCH_CACHE.length > 0) {
74
- return SEARCH_CACHE.filter(i => i.value.zipcode.includes(search));
99
+ return SEARCH_CACHE.filter(i => i.value.zipcode.includes(search)).slice(0, limit);
75
100
  }
76
101
  try {
77
- const { country = 'fr', limit = 5 } = options || {};
78
- const response = yield fetch(getUri(search, limit));
102
+ const response = yield fetch(getUri(search, departmentOnly));
79
103
  if (!response.ok)
80
104
  return Promise.reject(response);
81
105
  const result = yield response.json();
82
- const formatedResponse = responseFormat(result, country, search);
106
+ const formatedResponse = responseFormat(result, country, search, departmentOnly);
83
107
  if (isEqual(PREVIOUS_SEARCH, formatedResponse)) {
84
108
  const cleanValue = search.replace(' ', '').replace(PREVIOUS_VALUE, '');
85
- return PREVIOUS_SEARCH.filter(i => i.label.includes(cleanValue));
109
+ return PREVIOUS_SEARCH.filter(i => i.label.includes(cleanValue)).slice(0, limit);
86
110
  }
87
111
  PREVIOUS_VALUE = search;
88
112
  PREVIOUS_SEARCH = formatedResponse;
89
113
  if (isNumber && search.length !== 5) {
90
114
  SEARCH_CACHE = formatedResponse;
91
115
  }
92
- return formatedResponse;
116
+ return formatedResponse.slice(0, limit);
93
117
  }
94
118
  catch (error) {
95
119
  if (typeof error === 'string')
@@ -152,7 +176,7 @@ const get = (instance, search, options) => __awaiter(void 0, void 0, void 0, fun
152
176
  if (codeiso2 === '')
153
177
  return acc;
154
178
  const formatCountryName = convertFirstLetterToUpperCase(libcog.includes('(') ? libenr : libcog);
155
- const formatCog = cog.includes('X') ? `(${cog})` : '';
179
+ const formatCog = !cog.includes('X') ? `(${cog})` : '';
156
180
  const label = `${formatCountryName} ${formatCog}`;
157
181
  return [...acc, { label, value: codeiso2.toLowerCase() }];
158
182
  }, []);
@@ -8,11 +8,16 @@ interface MunicipalitySearchResult {
8
8
  }
9
9
  export interface MunicipalityApiResult {
10
10
  nom: string;
11
+ departement?: {
12
+ code: string;
13
+ nom: string;
14
+ };
11
15
  codesPostaux: string[];
12
16
  }
13
17
  interface Options {
14
- country: string;
15
- limit: number;
18
+ country?: string;
19
+ limit?: number;
20
+ departmentOnly?: boolean;
16
21
  }
17
22
  declare type MunicipalitySearch = (search: string, options?: Options) => Promise<MunicipalitySearchResult[] | string>;
18
23
  export declare const get: MunicipalitySearch;
@@ -1 +1 @@
1
- {"version":3,"file":"municipalitySearch.d.ts","sourceRoot":"","sources":["../src/municipalitySearch.ts"],"names":[],"mappings":"AAKA,UAAU,wBAAwB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE,MAAM,CAAA;KAChB,CAAA;CACF;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,UAAU,OAAO;IACf,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd;AAED,aAAK,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,wBAAwB,EAAE,GAAG,MAAM,CAAC,CAAA;AA0B7G,eAAO,MAAM,GAAG,EAAE,kBAsCjB,CAAA"}
1
+ {"version":3,"file":"municipalitySearch.d.ts","sourceRoot":"","sources":["../src/municipalitySearch.ts"],"names":[],"mappings":"AAKA,UAAU,wBAAwB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE,MAAM,CAAA;KAChB,CAAA;CACF;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;IACD,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,UAAU,OAAO;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,aAAK,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,wBAAwB,EAAE,GAAG,MAAM,CAAC,CAAA;AAmD7G,eAAO,MAAM,GAAG,EAAE,kBAoCjB,CAAA"}
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export declare const convertFirstLetterToUpperCase: (str: string) => string;
2
- export declare const getUri: (search: string, limit: number) => string;
2
+ export declare const getUri: (search: string, departmentOnly: boolean) => string;
3
3
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,6BAA6B,QAAS,MAAM,WAMxD,CAAA;AAED,eAAO,MAAM,MAAM,WAAY,MAAM,SAAS,MAAM,WAanD,CAAA"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,6BAA6B,QAAS,MAAM,WAMxD,CAAA;AAED,eAAO,MAAM,MAAM,WAAY,MAAM,kBAAkB,OAAO,WAa7D,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pretto/places",
3
- "version": "0.3.0",
3
+ "version": "0.7.0",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",