@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 +145 -0
- package/dist/index.js +39 -15
- package/dist/module.js +39 -15
- package/dist/municipalitySearch.d.ts +7 -2
- package/dist/municipalitySearch.d.ts.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
# @pretto/places
|
2
|
+
|
3
|
+
[](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
|
+

|
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,
|
49
|
+
const getUri = (search, departmentOnly) => {
|
50
50
|
const PLACES_API = 'https://geo.api.gouv.fr';
|
51
|
-
const QUERY_FIELDS =
|
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}
|
55
|
-
municipality: `${PLACES_API}/communes?nom=${formatedSearch}&${QUERY_FIELDS}
|
56
|
-
zipcode: `${PLACES_API}/communes?codePostal=${formatedSearch}&${QUERY_FIELDS}
|
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 [
|
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 [
|
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
|
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,
|
39
|
+
const getUri = (search, departmentOnly) => {
|
40
40
|
const PLACES_API = 'https://geo.api.gouv.fr';
|
41
|
-
const QUERY_FIELDS =
|
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}
|
45
|
-
municipality: `${PLACES_API}/communes?nom=${formatedSearch}&${QUERY_FIELDS}
|
46
|
-
zipcode: `${PLACES_API}/communes?codePostal=${formatedSearch}&${QUERY_FIELDS}
|
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 [
|
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 [
|
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
|
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
|
15
|
-
limit
|
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;
|
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
package/dist/utils.d.ts.map
CHANGED
@@ -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,
|
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"}
|