From 8dd2b9f4651fe6cc9ef388f0f1b461752a2f7d47 Mon Sep 17 00:00:00 2001 From: Sanjay Achar Date: Fri, 19 Jul 2024 23:07:49 +0530 Subject: [PATCH] Routing Directions API (#2) * Routing directions API * fixing lint errors * adding badge * Update README.md * updating readme file * adding badges to readme --- README.md | 114 +++++++++++++++++------------- dev_test/index.ts | 3 +- dev_test/places.ts | 2 +- dev_test/routing.ts | 13 ++++ documentation/places.md | 82 +++++++++++++++++++++ documentation/routing.md | 43 +++++++++++ package.json | 8 +-- src/const.ts | 1 + src/index.ts | 1 + src/routing.ts | 141 +++++++++++++++++++++++++++++++++++++ src/types/http-response.ts | 53 ++++++++++++++ src/types/language.ts | 2 +- 12 files changed, 408 insertions(+), 55 deletions(-) create mode 100644 dev_test/routing.ts create mode 100644 documentation/places.md create mode 100644 documentation/routing.md create mode 100644 src/routing.ts diff --git a/README.md b/README.md index 8c1aa9e..4c4d0bc 100644 --- a/README.md +++ b/README.md @@ -1,65 +1,83 @@ -# OLA Maps SDK (WIP) -A Node.js Library for Easy Integration with OLA Maps API +# OLA Maps SDK +This JavaScript SDK provides a seamless interface to interact with the OLA Maps API, simplifying geocoding, reverse geocoding, and routing operations. +
+
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/cebb7bf6c07048ccbd6fdf756d56b0bf)](https://app.codacy.com/gh/iSanjayAchar/ola-maps-node-sdk/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) +[![Codacy Badge](https://app.codacy.com/project/badge/Coverage/cebb7bf6c07048ccbd6fdf756d56b0bf)](https://app.codacy.com/gh/iSanjayAchar/ola-maps-node-sdk/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage) +[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) +![NPM Version](https://img.shields.io/npm/v/ola-maps) +![Licence](https://img.shields.io/badge/license-MIT-blue) ### Installation +Install the SDK using npm: +```bash +npm i --save ola-maps ``` -npm i -S ola-maps -# OR +Or using yarn: +```bash yarn add ola-maps ``` +### Modules +The SDK consists of two main modules: +1. **Places**: Provides functionality for autocomplete, geocoding, and reverse geocoding. For more details, check the [Places documentation](/documentation/places.md). +2. **Routing**: Enables the calculation of directions between locations. For more details, check the [Routing documentation](/documentation/routing.md) + ### Authentication -While OLA Map APIs support two type of authentication, this SDK only supports only authentication using `API_KEY`. To generate `API_KEY`, check the documentation - https://maps.olakrutrim.com/docs/auth +This SDK supports authentication using `API_KEY`. Generate your API key by following the instructions in the OLA Maps documentation: https://maps.olakrutrim.com/docs/auth -### Support -1. Places - - [x] Autocomplete - - [x] Geocode - - [x] Reverse Geocode -2. Routing - - [ ] Direction +### Basic Example +```javascript +import { Places, Routing } from "ola-maps"; -### Places -Comprehensive set of APIs to access OLA Maps API with ease +const placesClient = new Places("YOUR_API_KEY"); +const routingClient = new Routing("YOUR_API_KEY"); -#### Auto Complete -Autocomplete provides intuitive suggestions of places to be looked up. This helps accurate lookup of places based on the text provided. This solves a lot of use cases like lookup of popular places like restaurants, malls, etc. +async function main() { + const autocompleteResult = await placesClient.autocomplete("Koramangala"); + console.log(autocompleteResult); -``` -import { Places } from "ola-maps"; + const geocodeResult = await placesClient.geocode("Regent Insignia, 4th Block, 17th Main, Koramangala"); + console.log(geocodeResult); -const places = new Places("API_KEY", "VERSION"); // Version is optional + const reverseGeocodeResult = await placesClient.reverse_geocode(12.9716, 77.5946); + console.log(reverseGeocodeResult); -async function query(input) { - const result = places.autocomplete(input); - console.log(result); + const origin = { lat: 12.9716, lng: 77.5946 }; // Bengaluru + const destination = { lat: 19.0760, lng: 72.8777 }; // Mumbai + const directionResult = await routingClient.direction(origin, destination); + console.log(directionResult); } -``` - -#### Geocode -Forward Geocoding API helps translate real-world text-based addresses into geographic coordinates. This is useful in mapping services, route planning, location-based searches, and delivery logistics. +main(); ``` -import { Places } from "ola-maps"; -const places = new Places("API_KEY", "VERSION"); // Version is optional - -async function query(input) { - const result = places.geocode(input); - console.log(result); -} -``` - -#### Reverse Geocode -Reverse Geocoding API helps in translating coordinates to real world text based addressing. This is helpful in scenarios like taxi pickup, taxi drop, delivery/courier, etc. - -``` -import { Places } from "ola-maps"; - -const places = new Places("API_KEY", "VERSION"); // Version is optional - -async function query(input) { - const result = places.reverse_geocode(input); - console.log(result); -} -``` \ No newline at end of file +### Issues +If you encounter any problems or have feature requests, please file an issue on our GitHub repository - https://github.com/iSanjayAchar/ola-maps-node-sdk/issues/new + +### Contributors ✨ + + + + + +
+ + Kent C. Dodds +
+ + Sanjay Achar + +
+
+ + Kent C. Dodds +
+ + Jeevan V + +
+
+ +### Licence +This SDK is released under the MIT License. diff --git a/dev_test/index.ts b/dev_test/index.ts index 09c4f5d..d1572a8 100644 --- a/dev_test/index.ts +++ b/dev_test/index.ts @@ -1,4 +1,5 @@ import * as dotenv from "dotenv"; dotenv.config(); -import "./places"; \ No newline at end of file +// import "./places"; +import "./routing"; \ No newline at end of file diff --git a/dev_test/places.ts b/dev_test/places.ts index 8bc0ec8..86cd678 100644 --- a/dev_test/places.ts +++ b/dev_test/places.ts @@ -6,4 +6,4 @@ const places = new Places(apiKey); // places.autocomplete("sadsadsadsadsadsdsads").then(console.log).catch(console.error) // places.geocoding("271").then(console.log).catch(console.error); -places.reverse_geocoding("12.931316595874005", "77.61649243443775").then(console.log).catch(console.error); \ No newline at end of file +places.reverse_geocode("12.931316595874005", "77.61649243443775").then(console.log).catch(console.error); \ No newline at end of file diff --git a/dev_test/routing.ts b/dev_test/routing.ts new file mode 100644 index 0000000..e63c7c5 --- /dev/null +++ b/dev_test/routing.ts @@ -0,0 +1,13 @@ +import {Routing} from "../src"; + +const apiKey = process.env.OLA_MAPS_API_KEY as string; + +const routing = new Routing(apiKey); + +routing.direction({ + lat: "18.76029027465273", + lng: "73.3814242364375" +}, { + lat: "18.73354223011708", + lng: "73.44587966939002" +}).then(console.log).catch(console.error); \ No newline at end of file diff --git a/documentation/places.md b/documentation/places.md new file mode 100644 index 0000000..e78b851 --- /dev/null +++ b/documentation/places.md @@ -0,0 +1,82 @@ +# Places API +This JavaScript library provides a client to interact with the Places API. It simplifies the process of making autocomplete, geocoding, and reverse geocoding requests. It uses Axios under the hood for making HTTP requests. + +### Usage +To use the client, you'll need an API key. Create a new instance of the Places class and pass your API key and optional version (defaulting to `v1`) + +**Note:** An API key from the Places service is required for authentication. More details regarding the authentication can be found here. + +### Methods +The `Places` class provides the following methods: +1. `autocomplete(input, options?)` + - Performs autocomplete based on the provided input. + - `input` - The user's search input. + - `options` - (Optional) Additional options like language, location, radius, etc...
+ ```typescript + type PlacesOption = { + "X-Request-Id"?: string; + "X-Correlation-Id"?: string; + language?: ILanguage; + location?: { + latitude: string | number; + longitude: string | number; + }; + radius?: number; + strictbounds?: boolean; + } + ``` +2. `geocode(address, options?)` + - Converts an address into geographic coordinates (latitude and longitude). + - `address` - The address to geocode. + - `options` - (Optional) Additional options like language, bounding box, etc...
+ ```typescript + type GeocodingOption = { + "X-Request-Id"?: string; + "X-Correlation-Id"?: string; + language?: ILanguage; + bounding?: { + x: { + latitude: string | number; + longitude: string | number; + }, + y: { + latitude: string | number; + longitude: string | number; + } + } + } + ``` +3. `reverse_geocode(lat, lng, options?)` + - Converts latitude and longitude into an address. + - `lat` - The latitude coordinate. + - `lng` - The longitude coordinate. + - `options` - (Optional) Additional options like correlation ID and request ID. + ```typescript + type ReverseGeocodingOption = { + "X-Request-Id"?: string; + "X-Correlation-Id"?: string; + } + ``` + +### Example +```javascript +async function main() { + import { Places } from "ola-maps"; + + const placesClient = new Places("YOUR_API_KEY"); + + // Autocomplete + const autocompleteResult = await placesClient.autocomplete("Koramangala"); + console.log(autocompleteResult); + + // Geocoding + const geocodeResult = await placesClient.geocode("Regent Insignia, 4thBlock, 17th Main, Koramangala"); + console.log(geocodeResult); + + // Reverse Geocoding + const reverseGeocodeResult = await placesClient.reverse_geocode(37.4221, -122.0841); + console.log(reverseGeocodeResult); +} + +main(); +``` diff --git a/documentation/routing.md b/documentation/routing.md new file mode 100644 index 0000000..393d595 --- /dev/null +++ b/documentation/routing.md @@ -0,0 +1,43 @@ +# Places API +This JavaScript library provides a client to interact with the OLA Maps Routing API. It simplifies the process of calculating directions between locations using Axios for HTTP requests + +### Usage +To use the client, you'll need an API key. Create a new instance of the Routing class and pass your API key and optional version (defaulting to `v1`) + +**Note:** An API key from the Places service is required for authentication. More details regarding the authentication can be found here. + +### Methods +The `Routing` class provides the following methods: +1. `direction(origin, destination, options?)` + - `origin` (Coordinates) - Object with lat (latitude) and lng (longitude) of the starting point. + - `destination` (Coordinates) - Object with lat (latitude) and lng (longitude) of the ending point. + - `options` - (Optional) Additional options like language, location, radius, etc...
+ ```typescript + type DirectionOptions = { + "X-Request-Id"?: string; + "X-Correlation-Id"?: string; + waypoints?: Array<[string | number, string | number]>; + alternatives?: boolean; + steps?: boolean; + overview?: "full" | "simplied" | false; + language?: ILanguage; + traffic_metadata?: boolean; + } + ``` + +### Example +```javascript +import { Routing } from "ola-maps"; + +async function main() { + const routing = new Routing("YOUR_API_KEY"); + + const origin = { lat: 12.9716, lng: 77.5946 }; // Bengaluru + const destination = { lat: 19.0760, lng: 72.8777 }; // Mumbai + + const directionResult = await routing.direction(origin, destination); + console.log(directionResult); +} + +main(); +``` diff --git a/package.json b/package.json index 0bad495..cec317f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ola-maps", - "version": "0.0.4", - "description": "A Node.js Library for Easy Integration with OLA Maps API", + "version": "0.0.5", + "description": "JavaScript SDK for a seamless interface to interact with the OLA Maps API, simplifying geocoding, reverse geocoding, and routing operations.", "keywords": [ "ola", "ola maps", @@ -20,10 +20,10 @@ ], "license": "MIT", "author": "isanjayachar ; + alternatives?: boolean; + steps?: boolean; + overview?: "full" | "simplied" | false; + language?: ILanguage; + traffic_metadata?: boolean; +} + +/** + * Client for interacting with the OLA Maps Routing API. + * + * This class provides methods for calculating directions between locations, + * handling authentication, and managing API requests. + */ +export class Routing { + /** + * API key for authentication with the Places service. + * @private + */ + private apiKey = ""; + + /** + * The API version to use. Defaults to 'v1'. + * @private + */ + private version: IVersion = "v1"; + + /** + * The Axios instance used for making HTTP requests. + * @private + */ + private httpClient: AxiosInstance = {} as AxiosInstance; + + /** + * Creates a new Places client. + * @param apiKey - Your API key for the Places service. + * @param version - (Optional) The API version to use. Defaults to 'v1'. + * @throws {Error} If the API key is missing or invalid. + */ + constructor( + apiKey: string, + version: IVersion = "v1", + ) { + if (!apiKey || apiKey.trim() === "") { + throw new Error("API Key is required. Check documentation - https://maps.olakrutrim.com/docs/auth"); + } + + this.apiKey = apiKey; + this.version = version; + this.init(); + } + + /** + * Initializes the Places client by setting up the Axios instance and environment variables. + * @private + */ + private init(): void { + const env = ENV[this.version]; + process.env.API_VERSION = this.version; + + for (const variable in env) { + if (env[variable]) { + process.env[variable] = env[variable]; + } + } + + this.httpClient = httpClientInit(this.apiKey); + } + + /** + * Calculates directions between an origin and destination, with optional parameters. + * + * @async + * @param {Coordinates} origin - An object with `lat` (latitude) and `lng` (longitude) properties representing the starting point. + * @param {Coordinates} destination - An object with `lat` and `lng` properties representing the ending point. + * @param {DirectionOptions} [options] - Optional parameters for customizing the direction request. + * @returns {Promise>} A Promise that resolves to a standardized API response containing the direction results. + * @throws {Error} If an error occurs during the API request, the Promise will be rejected with the error. + */ + public async direction(origin: Coordinates, destination: Coordinates, options?: DirectionOptions): Promise> { + try { + let path = `${process.env.directionPath}?origin=${origin.lat},${origin.lng}&destination=${destination.lat},${destination.lng}&`; + + if (options) { + if (options["X-Correlation-Id"]) { + path += `X-Correlation-Id=${options["X-Correlation-Id"]}&`; + } + + if (options["X-Request-Id"]) { + path += `X-Request-Id=${options["X-Request-Id"]}&`; + } + + if (options.language) { + path += `language=${options.language}&`; + } + + if (typeof options.alternatives === "boolean") { + path += `alternatives=${options.alternatives}&`; + } + + if (typeof options.traffic_metadata === "boolean") { + path += `traffic_metadata=${options.traffic_metadata}&`; + } + + if (typeof options.steps === "boolean") { + path += `steps=${options.steps}&`; + } + + if (typeof options.overview === "boolean" || typeof options.overview === "string") { + path += `overview=${options.overview}&s`; + } + + if (options.waypoints) { + path += `waypoints=${options.waypoints.map((points) => points.join(",")).join("|")}&`; + } + } + + if (path.endsWith("&") || path.endsWith("?")) { + path = path.slice(0, -1); + } + + const {data}: AxiosResponse> = await this.httpClient.post(path, ""); + return Promise.resolve(data); + } catch (err) { + return Promise.reject(err); + } + } +} diff --git a/src/types/http-response.ts b/src/types/http-response.ts index f72fbcb..0e103f7 100644 --- a/src/types/http-response.ts +++ b/src/types/http-response.ts @@ -113,3 +113,56 @@ export type IReverseGeocodingResult = { layer: Array; }>; }; + +export type IDirectionResult = { + status: IStatus; + source_from: string; + geocoded_waypoints: Array<{ + geocoder_status: IStatus; + place_id: string; + types: Array; + }>; + routes: Array<{ + bounds: Record; + copyrights: string; + legs: Array<{ + distance: number; + readable_distance: string; + duration: string; + readable_duration: string; + start_address: string; + end_address: string; + start_location: { + lat: number; + lng: number; + }; + end_location: { + lat: number; + lng: number; + }; + steps: Array<{ + distance: number; + readable_distance: string; + duration: number; + readable_duration: string; + start_location: { + lat: number; + lng: number; + }; + end_location: { + lat: number; + lng: number; + }; + instructions: string; + maneuver: string; + bearing_before: number; + bearing_after: number; + }> + }>; + overview_polyline: string; + travel_advisory: string; + summary: string; + warnings: Array; + waypoint_order: Record; + }>; +}; diff --git a/src/types/language.ts b/src/types/language.ts index b81baf2..523014c 100644 --- a/src/types/language.ts +++ b/src/types/language.ts @@ -1 +1 @@ -export type ILanguage = "en"; +export type ILanguage = "en" | "kn" | "hi";