diff --git a/spec/__snapshots__/azure.spec.ts.snap b/spec/__snapshots__/azure.spec.ts.snap new file mode 100644 index 0000000..ba37564 --- /dev/null +++ b/spec/__snapshots__/azure.spec.ts.snap @@ -0,0 +1,27 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`L.Control.Geocoder.AzureMaps > geocodes 1`] = ` +[ + [ + [ + { + "bbox": { + "_northEast": { + "lat": 47.6317, + "lng": -122.13717, + }, + "_southWest": { + "lat": 47.6299, + "lng": -122.13983, + }, + }, + "center": { + "lat": 47.6308, + "lng": -122.1385, + }, + "name": "15127 NE 24th St, Redmond, WA 980525544", + }, + ], + ], +] +`; diff --git a/spec/azure.spec.ts b/spec/azure.spec.ts new file mode 100644 index 0000000..739a6bd --- /dev/null +++ b/spec/azure.spec.ts @@ -0,0 +1,81 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { GeocodingResult } from '../src/geocoders/api'; +import { AzureMaps } from '../src/geocoders/azure'; +import { mockFetchRequest } from './mockFetchRequest'; + +describe('L.Control.Geocoder.AzureMaps', () => { + afterEach(() => vi.clearAllMocks()); + it('geocodes', async () => { + const geocoder = new AzureMaps({ apiKey: 'xxx' }); + const result = await mockFetchRequest( + 'https://atlas.microsoft.com/search/address/json?api-version=1.0&query=15127+NE+24th+Street%2C+Redmond%2C+WA+98052&subscription-key=xxx', + { + summary: { + query: '15127 NE 24th Street, Redmond, WA 98052', + queryType: 'NON_NEAR', + queryTime: 58, + numResults: 1, + offset: 0, + totalResults: 1, + fuzzyLevel: 1 + }, + results: [ + { + type: 'Point Address', + id: 'US/PAD/p0/19173426', + score: 14.51, + address: { + streetNumber: '15127', + streetName: 'NE 24th St', + municipalitySubdivision: 'Redmond', + municipality: 'Redmond, Adelaide, Ames Lake, Avondale, Earlmount', + countrySecondarySubdivision: 'King', + countryTertiarySubdivision: 'Seattle East', + countrySubdivisionCode: 'WA', + postalCode: '98052', + extendedPostalCode: '980525544', + countryCode: 'US', + country: 'United States Of America', + countryCodeISO3: 'USA', + freeformAddress: '15127 NE 24th St, Redmond, WA 980525544', + countrySubdivisionName: 'Washington' + }, + position: { + lat: 47.6308, + lon: -122.1385 + }, + viewport: { + topLeftPoint: { + lat: 47.6317, + lon: -122.13983 + }, + btmRightPoint: { + lat: 47.6299, + lon: -122.13717 + } + }, + entryPoints: [ + { + type: 'main', + position: { + lat: 47.6315, + lon: -122.13852 + } + } + ] + } + ] + }, + () => geocoder.geocode('15127 NE 24th Street, Redmond, WA 98052') + ); + + const feature: GeocodingResult = result[0]; + expect(feature.name).toBe('15127 NE 24th St, Redmond, WA 980525544'); + expect(feature.center).toStrictEqual({ lat: 47.6308, lng: -122.1385 }); + expect(feature.bbox).toStrictEqual({ + _northEast: { lat: 47.6317, lng: -122.13717 }, + _southWest: { lat: 47.6299, lng: -122.13983 } + }); + expect([[result]]).toMatchSnapshot(); + }); +}); diff --git a/src/geocoders/azure.ts b/src/geocoders/azure.ts index 89cbf5a..fd79afd 100644 --- a/src/geocoders/azure.ts +++ b/src/geocoders/azure.ts @@ -8,7 +8,9 @@ export interface AzureMapsOptions { } /** - * Azure Maps Geocoder class + * Implementation of [Azure Maps Geocoding](https://www.microsoft.com/en-us/maps/azure/location-services/geocoding) + * + * https://learn.microsoft.com/en-us/rest/api/maps/search?view=rest-maps-1.0 */ export class AzureMaps implements IGeocoder { private options: AzureMapsOptions = { @@ -23,6 +25,10 @@ export class AzureMaps implements IGeocoder { } } + /** + * {@inheritdoc} + * https://learn.microsoft.com/en-us/rest/api/maps/search/get-search-address?view=rest-maps-1.0&tabs=HTTP + */ async geocode(query: string): Promise { const params = { 'api-version': '1.0', @@ -30,7 +36,7 @@ export class AzureMaps implements IGeocoder { 'subscription-key': this.options.apiKey }; const url = this.options.serviceUrl + '/address/json'; - const data = await getJSON(url, params); + const data = await getJSON(url, params); const results: GeocodingResult[] = []; if (data.results && data.results.length > 0) { @@ -48,6 +54,10 @@ export class AzureMaps implements IGeocoder { return results; } + /** + * {@inheritdoc} + * https://learn.microsoft.com/en-us/rest/api/maps/search/get-search-address-reverse?view=rest-maps-1.0&tabs=HTTP + */ async reverse(location: L.LatLngLiteral, scale: number): Promise { const params = { 'api-version': '1.0', @@ -81,3 +91,63 @@ export class AzureMaps implements IGeocoder { export function azure(options: AzureMapsOptions) { return new AzureMaps(options); } + +/** + * @internal + */ +export interface AzureMapsResponse { + summary: Summary; + results: Result[]; +} + +interface Result { + type: string; + id: string; + score: number; + address: Address; + position: Position; + viewport: Viewport; + entryPoints: EntryPoint[]; +} + +interface Address { + streetNumber: string; + streetName: string; + municipalitySubdivision: string; + municipality: string; + countrySecondarySubdivision: string; + countryTertiarySubdivision: string; + countrySubdivisionCode: string; + postalCode: string; + extendedPostalCode: string; + countryCode: string; + country: string; + countryCodeISO3: string; + freeformAddress: string; + countrySubdivisionName: string; +} + +interface EntryPoint { + type: string; + position: Position; +} + +interface Position { + lat: number; + lon: number; +} + +interface Viewport { + topLeftPoint: Position; + btmRightPoint: Position; +} + +interface Summary { + query: string; + queryType: string; + queryTime: number; + numResults: number; + offset: number; + totalResults: number; + fuzzyLevel: number; +}