@@ -4,11 +4,17 @@ export async function googleGeocode({ apiKey, query }) {
4
4
) ;
5
5
const data = await response . json ( ) ;
6
6
7
- if ( data . status === 'OK' ) {
8
- return data . results [ 0 ] ;
9
- } else {
7
+ if ( data . status !== 'OK' || data . results . length === 0 ) {
10
8
return null ;
11
9
}
10
+
11
+ const result = data . results [ 0 ] ;
12
+
13
+ return createGeocodingResult ( {
14
+ geometry : result . geometry ,
15
+ formatted_address : result . formatted_address ,
16
+ name : result . formatted_address
17
+ } ) ;
12
18
}
13
19
14
20
export async function googlePlacesAutocomplete ( { apiKey, input } ) {
@@ -22,5 +28,158 @@ export async function googlePlacesAutocomplete({ apiKey, input }) {
22
28
} ) ;
23
29
const data = await response . json ( ) ;
24
30
25
- return data . suggestions ;
31
+ if ( ! data . suggestions ) {
32
+ return [ ] ;
33
+ }
34
+
35
+ const suggestions = [ ] ;
36
+ for ( const suggestion of data . suggestions ) {
37
+ const prediction = suggestion . placePrediction ;
38
+
39
+ const suggestionObject = createSuggestion (
40
+ prediction . placeId ,
41
+ prediction . text . text ,
42
+ prediction . text . text
43
+ ) ;
44
+
45
+ if ( suggestionObject ) {
46
+ suggestions . push ( suggestionObject ) ;
47
+ }
48
+ }
49
+
50
+ return suggestions ;
51
+ }
52
+
53
+ export async function bingGeocode ( { apiKey, query } ) {
54
+ const rawBingResult = await fetch (
55
+ `https://dev.virtualearth.net/REST/v1/Locations?query=${ encodeURIComponent ( query ) } &key=${ apiKey } ` ,
56
+ {
57
+ method : 'GET' ,
58
+ headers : { Accept : 'application/json' }
59
+ }
60
+ ) ;
61
+
62
+ const data = await rawBingResult . json ( ) ;
63
+
64
+ if ( data . resourceSets [ 0 ] . estimatedTotal === 0 ) {
65
+ return null ;
66
+ }
67
+
68
+ const resource = data . resourceSets [ 0 ] . resources [ 0 ] ;
69
+
70
+ return createGeocodingResult ( {
71
+ geometry : {
72
+ location : {
73
+ lat : resource . point . coordinates [ 0 ] ?? null ,
74
+ lng : resource . point . coordinates [ 1 ] ?? null
75
+ }
76
+ } ,
77
+ formatted_address : resource . address . formattedAddress ,
78
+ name : resource . name ?? '' ,
79
+ placeId : null
80
+ } ) ;
81
+ }
82
+
83
+ export async function bingAutoSuggestPlaces ( { apiKey, query } ) {
84
+ const rawBingResult = await fetch (
85
+ `https://dev.virtualearth.net/REST/v1/Autosuggest?query=${ encodeURIComponent ( query ) } &key=${ apiKey } ` ,
86
+ {
87
+ method : 'GET' ,
88
+ headers : { Accept : 'application/json' }
89
+ }
90
+ ) ;
91
+
92
+ const data = await rawBingResult . json ( ) ;
93
+
94
+ const resourceSets = data . resourceSets ;
95
+
96
+ if ( ! resourceSets || resourceSets . length === 0 || resourceSets [ 0 ] . estimatedTotal === 0 ) {
97
+ return [ ] ;
98
+ }
99
+
100
+ const resources = resourceSets [ 0 ] . resources ;
101
+ if ( ! resources || resources . length === 0 ) {
102
+ return [ ] ;
103
+ }
104
+
105
+ const suggestions = [ ] ;
106
+ for ( const resource of resources ) {
107
+ if ( resource . value && Array . isArray ( resource . value ) ) {
108
+ for ( const item of resource . value ) {
109
+ const displayText = item . name
110
+ ? `${ item . name } - ${ item . address . formattedAddress } `
111
+ : item . address . formattedAddress ;
112
+
113
+ const suggestion = createSuggestion (
114
+ null ,
115
+ item . name || item . address . formattedAddress ,
116
+ displayText
117
+ ) ;
118
+
119
+ if ( suggestion ) {
120
+ suggestions . push ( suggestion ) ;
121
+ }
122
+ }
123
+ } else {
124
+ const suggestion = createSuggestion (
125
+ null ,
126
+ resource . name || resource . address . formattedAddress ,
127
+ resource . address . formattedAddress
128
+ ) ;
129
+
130
+ if ( suggestion ) {
131
+ suggestions . push ( suggestion ) ;
132
+ }
133
+ }
134
+ }
135
+
136
+ return suggestions ;
137
+ }
138
+
139
+ export async function fetchAutocompleteResults ( provider , query , apiKey ) {
140
+ switch ( provider ) {
141
+ case 'google' :
142
+ return await googlePlacesAutocomplete ( { apiKey, input : query } ) ;
143
+ case 'bing' :
144
+ return await bingAutoSuggestPlaces ( { apiKey, query } ) ;
145
+ default :
146
+ throw new Error ( 'Invalid geocoding provider' ) ;
147
+ }
148
+ }
149
+
150
+ /**
151
+ *
152
+ * @param {string } placeId optional - some providers return a placeId
153
+ * @param {string } name required - used for geocoding the selected place
154
+ * @param {string } displayText required - used for displaying the selected place
155
+ * @returns
156
+ */
157
+ function createSuggestion ( placeId , name , displayText ) {
158
+ if ( ! name || ! displayText ) return null ;
159
+
160
+ return {
161
+ ...( placeId && { placeId } ) ,
162
+ name,
163
+ displayText
164
+ } ;
165
+ }
166
+
167
+ /**
168
+ *
169
+ * @param {location{lat,lng} } geometry
170
+ * @param {string } formatted_address
171
+ * @param {string } name
172
+ * @returns
173
+ */
174
+ function createGeocodingResult ( { geometry, formatted_address, name } ) {
175
+ return {
176
+ name : name || formatted_address ,
177
+ formatted_address : formatted_address ,
178
+ geometry : {
179
+ location : {
180
+ lat : geometry . location . lat ,
181
+ lng : geometry . location . lng
182
+ }
183
+ }
184
+ } ;
26
185
}
0 commit comments