@tomtom-org/maps-sdk 0.45.10 → 0.45.12

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.
@@ -1 +1 @@
1
- {"version":3,"file":"services.es.js","sources":["../src/shared/types/apiResponseErrorTypes.ts","../src/shared/errors.ts","../src/shared/schema/commonParamsSchema.ts","../src/shared/schema/validation.ts","../src/shared/serviceTemplate.ts","../src/shared/fetch.ts","../src/shared/schema/geometriesSchema.ts","../src/autocomplete-search/autocompleteSearchRequestSchema.ts","../src/shared/request/requestBuildingUtils.ts","../src/shared/request/commonSearchRequestBuilder.ts","../src/autocomplete-search/requestBuilder.ts","../src/shared/geometry.ts","../src/autocomplete-search/responseParser.ts","../src/autocomplete-search/autocompleteSearchTemplate.ts","../src/autocomplete-search/autocompleteSearch.ts","../src/autocomplete-search/customize.ts","../src/ev-charging-stations-availability/evChargingStationsAvailabilityRequestSchema.ts","../src/ev-charging-stations-availability/requestBuilder.ts","../src/shared/ev.ts","../src/ev-charging-stations-availability/connectorAvailability.ts","../src/shared/searchResultParsing.ts","../src/ev-charging-stations-availability/responseParser.ts","../src/ev-charging-stations-availability/evChargingStationsAvailabilityTemplate.ts","../src/ev-charging-stations-availability/evChargingStationsAvailabilityResponseErrorParser.ts","../src/ev-charging-stations-availability/customize.ts","../src/shared/schema/commonGeocodeAndFuzzySearchParamsSchema.ts","../src/shared/schema/commonPlacesParamsSchema.ts","../src/geocode/geocodingRequestSchema.ts","../src/shared/arrays.ts","../src/geocode/requestBuilder.ts","../src/geocode/responseParser.ts","../src/geocode/geocodingTemplate.ts","../src/geocode/customize.ts","../src/geometry-data/geometryDataRequestSchema.ts","../src/geometry-data/requestBuilder.ts","../src/geometry-data/responseParser.ts","../src/geometry-data/geometryDataTemplate.ts","../src/geometry-data/customize.ts","../src/search/commonSearchParamsSchema.ts","../src/geometry-search/geometrySearchRequestSchema.ts","../src/geometry-search/requestBuilder.ts","../src/geometry-search/responseParser.ts","../src/geometry-search/geometrySearchTemplate.ts","../src/geometry-search/geometrySearch.ts","../src/geometry-search/customize.ts","../src/place-by-id/placeByIdSchema.ts","../src/place-by-id/requestBuilder.ts","../src/place-by-id/responseParser.ts","../src/place-by-id/placeByIdTemplate.ts","../src/place-by-id/customize.ts","../src/routing/routingResponseErrorParser.ts","../src/shared/schema/vehicleParamsSchema.ts","../src/shared/types/vehicleRestrictionParams.ts","../src/shared/schema/commonRoutingRequestSchema.ts","../src/shared/types/commonRoutingParams.ts","../src/reachable-range/types/reachableRangeParams.ts","../src/reachable-range/reachableRangeRequestSchema.ts","../src/shared/request/routingVehicleParamsBuilder.ts","../src/shared/request/commonRoutingRequestBuilder.ts","../src/reachable-range/requestBuilder.ts","../src/reachable-range/responseParser.ts","../src/reachable-range/reachableRangeTemplate.ts","../src/reachable-range/customize.ts","../src/revgeo/requestBuilder.ts","../src/revgeo/responseParser.ts","../src/revgeo/revGeocodeRequestSchema.ts","../src/revgeo/reverseGeocodingTemplate.ts","../src/revgeo/customize.ts","../src/routing/calculateRouteRequestSchema.ts","../src/routing/requestBuilder.ts","../src/routing/responseParser.ts","../src/routing/calculateRouteTemplate.ts","../src/routing/customize.ts","../src/traffic-incident-details/requestBuilder.ts","../src/traffic-incident-details/responseParser.ts","../src/traffic-incident-details/trafficIncidentDetailsTemplate.ts","../src/traffic-incident-details/trafficIncidentDetailsRequestSchema.ts","../src/customize/index.ts","../src/traffic-incident-details/customize.ts","../src/ev-charging-stations-availability/evChargingStationsAvailability.ts","../src/geocode/geocoding.ts","../src/geometry-data/geometryData.ts","../src/place-by-id/placeById.ts","../src/reachable-range/calculateReachableRange.ts","../src/revgeo/reverseGeocoding.ts","../src/routing/calculateRoute.ts","../src/fuzzy-search/fuzzySearchRequestSchema.ts","../src/fuzzy-search/responseParser.ts","../src/fuzzy-search/fuzzySearchTemplate.ts","../src/fuzzy-search/requestBuilder.ts","../src/search/search.ts","../src/fuzzy-search/fuzzySearch.ts","../src/traffic-incident-details/trafficIncidentDetails.ts"],"sourcesContent":["/**\n * @ignore\n */\nexport interface BaseAPIResponseErrorBody {\n /*\n * HTTP error code.\n */\n httpStatusCode: number;\n /*\n * Detailed information about the error.\n */\n detailedError: {\n /*\n * One of the defined error codes.\n */\n code: string;\n /*\n * A human-readable representation of the error code.\n */\n message: string;\n /*\n * Target of the particular error.\n * Value: The name of the request parameter.\n */\n target: string;\n };\n}\n\n/**\n * @ignore\n */\nexport interface DefaultAPIResponseErrorBody extends BaseAPIResponseErrorBody {\n /*\n * A human-readable description of the error code.\n */\n error?: string;\n errorText?: string;\n}\n\n/**\n * @ignore\n */\nexport interface RoutingAPIResponseError {\n /*\n * \tThe format version\n */\n formatVersion: string;\n error: {\n /*\n * A human-readable representation of the error code.\n */\n description: string;\n };\n detailedError: {\n /*\n * A human-readable representation of the error code.\n */\n message: string;\n /*\n * One of the defined error codes.\n */\n code: string;\n };\n}\n\n/**\n * Error returned by an API.\n * @ignore\n */\nexport type APIErrorResponse<T = DefaultAPIResponseErrorBody> = {\n status?: number;\n message: string;\n data?: T;\n};\n\n/**\n * @ignore\n */\nexport enum APICode {\n TOO_MANY_REQUESTS = 429,\n FORBIDDEN = 403,\n}\n","import type { ZodIssue } from 'zod';\nimport type { ValidationError } from './schema/validation';\nimport type { ParseResponseError } from './serviceTypes';\nimport type { APIErrorResponse, DefaultAPIResponseErrorBody } from './types/apiResponseErrorTypes';\nimport { APICode } from './types/apiResponseErrorTypes';\nimport type { ServiceName } from './types/servicesTypes';\n\n/**\n * Base error class for all SDK-related errors.\n *\n * The SDK handles two distinct categories of errors:\n * 1. **Programming errors**: Configuration or usage errors in the user's application,\n * such as passing incorrect types to parameters or functions.\n * 2. **API errors**: Recoverable errors that occur during SDK operations,\n * such as network failures or invalid API responses.\n *\n * @example\n * ```typescript\n * try {\n * // SDK operation\n * } catch (error) {\n * if (error instanceof SDKError) {\n * console.error(`Error in ${error.service}: ${error.message}`);\n * }\n * }\n * ```\n *\n * @group Errors\n */\nexport class SDKError extends Error {\n /**\n * Creates a new SDKError instance.\n *\n * @param message - Human-readable error description\n * @param service - Name of the service where the error occurred\n * @param issues - Optional array of Zod validation issues for detailed error information\n */\n constructor(\n message: string,\n readonly service: string,\n readonly issues?: ZodIssue[],\n ) {\n super(message);\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, SDKError);\n }\n }\n}\n\n/**\n * Mapping of API error codes to human-readable error messages.\n *\n * Provides standardized error messages for common API response codes,\n * ensuring consistent error handling across the SDK.\n *\n * @group Errors\n */\nexport const APIErrorCode: { readonly [K in APICode as number]: string } = {\n [APICode.TOO_MANY_REQUESTS]: 'Too Many Requests: The API Key is over QPS (Queries per second)',\n [APICode.FORBIDDEN]: 'Request failed with status code 403',\n};\n\n/**\n * Error class for HTTP API response errors.\n *\n * Extends {@link SDKError} to include HTTP status codes and automatically\n * maps known error codes to user-friendly messages using {@link APIErrorCode}.\n *\n * @example\n * ```typescript\n * throw new SDKServiceError('Invalid request', 'geocoding', 400);\n * ```\n *\n * @group Errors\n */\nexport class SDKServiceError extends SDKError {\n /**\n * HTTP status code of the failed API request.\n *\n * Common values:\n * - `400`: Bad Request\n * - `403`: Forbidden\n * - `429`: Too Many Requests\n * - `500`: Internal Server Error\n */\n status?: number;\n\n /**\n * Creates a new SDKServiceError instance.\n *\n * If the status code matches a known error in {@link APIErrorCode},\n * the message will be automatically replaced with the standardized message.\n *\n * @param message - Error message from the API or custom message\n * @param service - Name of the service that generated the error\n * @param status - HTTP status code of the failed request\n */\n constructor(message: string, service: string, status?: number) {\n super(message, service);\n this.status = status;\n\n /*\n * We use as message what returns from API if any, otherwise we have our APIErrorCode as a fallback\n * Check if there is a status and if the status exists in the mapped API error types\n */\n if (this.status && APIErrorCode[this.status]) {\n this.message = APIErrorCode[this.status];\n }\n }\n}\n\n/**\n * @ignore\n * @param error\n * @param serviceName\n */\nexport const parseDefaultResponseError: ParseResponseError<DefaultAPIResponseErrorBody> = (error, serviceName) => {\n const { data, message, status } = error;\n // Different services uses property error or errorText or detailedError\n // Here we cover all situations as a default error parser\n const errorMessage = data?.error || data?.errorText || message;\n return new SDKServiceError(errorMessage, serviceName, status);\n};\n\n/**\n * @ignore\n * Generate error for APIResponse, any other error type will be returned as it is.\n * @param error The error captured by a catch function.\n * @param serviceName The name of the service.\n * @param parseResponseError\n */\nexport const buildResponseError = (\n error: unknown,\n serviceName: ServiceName,\n parseResponseError?: ParseResponseError<unknown>,\n): SDKError => {\n if ((error as APIErrorResponse).status) {\n const fetchError = error as APIErrorResponse;\n if (parseResponseError) {\n return parseResponseError(fetchError, serviceName);\n }\n return parseDefaultResponseError(fetchError, serviceName);\n }\n\n return new SDKError((error as Error).message, serviceName);\n};\n\n/**\n * @ignore\n * @param error\n * @param serviceName\n */\nexport const buildValidationError = (error: ValidationError, serviceName: ServiceName): SDKError =>\n new SDKError(error.message, serviceName, error.issues);\n","import { z } from 'zod';\n\n/**\n * @ignore\n */\nexport const commonServiceRequestSchema = z.object({\n apiKey: z.string().optional().describe('TomTom API key for authentication'),\n commonBaseURL: z.string().optional().describe('Common base URL for all services'),\n customServiceBaseURL: z.string().optional().describe('Custom base URL for specific service'),\n language: z.string().optional().describe('Language code for response text (e.g., \"en-US\", \"nl-NL\")'),\n});\n","import type { ZodError } from 'zod';\nimport type { CommonServiceParams } from '../serviceTypes';\nimport type { RequestValidationConfig } from '../types/validation';\nimport { commonServiceRequestSchema } from './commonParamsSchema';\n\n/**\n * Format a Zod error into a human-readable string\n * @ignore\n */\nconst formatZodError = (error: ZodError): string => {\n return error.issues\n .map((issue) => {\n const path = issue.path.length > 0 ? `${issue.path.join('.')}: ` : '';\n return `${path}${issue.message}`;\n })\n .join('; ');\n};\n\n/**\n * Validate Error Class for validating params input, this will be used by SDKError class.\n * @ignore\n */\nexport class ValidationError extends Error {\n issues: ZodError['issues'];\n\n constructor(zodError: ZodError) {\n super(formatZodError(zodError));\n this.issues = zodError.issues;\n }\n}\n\n/**\n * @ignore\n * @param params\n * @param config\n */\nexport const validateRequestSchema = <T extends CommonServiceParams>(\n params: T,\n config?: RequestValidationConfig,\n): T => {\n const requestSchema = config?.schema\n ? commonServiceRequestSchema.extend(config.schema.shape)\n : commonServiceRequestSchema;\n\n // Apply all refinements using superRefine for better type compatibility in Zod v4\n const finalSchema = requestSchema.superRefine((data, ctx) => {\n // Validate common params\n if (!('commonBaseURL' in data) && !('customServiceBaseURL' in data)) {\n ctx.addIssue({\n code: 'custom',\n message: 'commonBaseURL or customServiceBaseURL is required',\n });\n }\n\n // Apply optional refinements\n if (config?.refinements?.length) {\n for (const refinement of config.refinements) {\n if (!refinement.check(data as T)) {\n ctx.addIssue({\n code: 'custom',\n message: refinement.message,\n });\n }\n }\n }\n });\n\n const validation = finalSchema.safeParse(params);\n if (!validation.success) {\n throw new ValidationError(validation.error);\n }\n\n return params;\n};\n","import { generateTomTomHeaders, mergeFromGlobal } from '@tomtom-org/maps-sdk/core';\nimport { buildResponseError, buildValidationError } from './errors';\nimport type { ValidationError } from './schema/validation';\nimport { validateRequestSchema } from './schema/validation';\nimport type { CommonServiceParams, ServiceTemplate } from './serviceTypes';\nimport type { ServiceName } from './types/servicesTypes';\n\n/**\n * @ignore\n * Template execution of a service call.\n * Any service goes through the same template steps:\n * 1- Build request\n * 2- Send request and get API response\n * 3- Parse and return API response\n * @param params The parameters for that specific service call.\n * @param template The implementation of the template steps.\n * @param serviceName The name of the service.\n */\nexport const callService = async <PARAMS extends CommonServiceParams, ApiRequest, ApiResponse, RESPONSE>(\n params: PARAMS,\n template: ServiceTemplate<PARAMS, ApiRequest, ApiResponse, RESPONSE>,\n serviceName: ServiceName,\n): Promise<RESPONSE> => {\n const customApiVersion = template.getAPIVersion?.(params);\n const mergedParams = mergeFromGlobal({ ...params, ...(customApiVersion && { apiVersion: customApiVersion }) });\n // (params.validateRequest defaults to true, thus true and undefined are the same)\n if (params.validateRequest === undefined || params.validateRequest) {\n try {\n validateRequestSchema<PARAMS>(mergedParams, template.requestValidation);\n } catch (e) {\n return Promise.reject(buildValidationError(e as ValidationError, serviceName));\n }\n }\n const apiRequest = template.buildRequest(mergedParams);\n const headers = generateTomTomHeaders(mergedParams);\n params.onAPIRequest?.(apiRequest);\n\n try {\n const apiResponse = await template.sendRequest(apiRequest, headers);\n params.onAPIResponse?.(apiRequest, apiResponse);\n return template.parseResponse(await apiResponse.data, mergedParams);\n } catch (e) {\n params.onAPIResponse?.(apiRequest, e);\n return Promise.reject(buildResponseError(e, serviceName, template.parseResponseError));\n }\n};\n","import type { TomTomHeaders } from '@tomtom-org/maps-sdk/core';\nimport type { FetchInput, ParsedFetchResponse, PostObject } from './types/fetch';\n\n/**\n * Custom error class for HTTP fetch errors.\n */\nclass FetchError extends Error {\n public readonly status: number;\n public readonly data?: unknown;\n\n constructor(status: number, message?: string, data?: unknown) {\n super(message ?? `HTTP Error ${status}`);\n this.name = 'FetchError';\n this.status = status;\n this.data = data;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, FetchError);\n }\n }\n}\n\n// Returns the response as a JSON object or throws an error if the response isn't successful.\nconst returnOrThrow = async <T>(response: Response): ParsedFetchResponse<T> => {\n if (response.ok) {\n return { data: await response.json(), status: response.status };\n }\n let message: string | undefined;\n let errorBody;\n const contentType = response.headers.get('content-type');\n if (response.bodyUsed) {\n message = response.statusText;\n } else if (contentType?.includes('application/json')) {\n errorBody = await response.json();\n message = errorBody?.errorText ?? errorBody?.message ?? errorBody?.detailedError?.message;\n } else if (contentType?.includes('text/xml')) {\n errorBody = await response.text();\n message = response.statusText;\n }\n\n throw new FetchError(response.status, message, errorBody);\n};\n\n/**\n * Fetches the given HTTP JSON resource with an HTTP GET request and returns a promise with the response as a JSON object.\n * If the response isn't successful, it returns a rejected promise with the http error code.\n * @ignore\n * @param url The URL to fetch.\n * @param headers The headers to be sent with the request.\n */\nexport const get = async <T>(url: URL, headers: TomTomHeaders): ParsedFetchResponse<T> =>\n returnOrThrow(await fetch(url, { headers }));\n\n/**\n * Fetches the given HTTP JSON resource with an HTTP POST request and returns a promise with the response as a JSON object.\n * If the response isn't successful, it returns a rejected promise with the http error code.\n * @ignore\n * @param input The POST object with URL and optional payload.\n * @param headers The headers to be sent with the request.\n */\nexport const post = async <T, D>(input: PostObject<D>, headers: TomTomHeaders): ParsedFetchResponse<T> =>\n returnOrThrow(\n await fetch(input.url, {\n method: 'POST',\n body: JSON.stringify(input.data),\n headers: { ...headers, 'Content-Type': 'application/json' },\n }),\n );\n\n/**\n * Fetches the given HTTP JSON resource with the given HTTP operation and URL/Payload as applicable.\n * * Useful for services which can use different HTTP methods depending on the parameters.\n * @param input The input object (e.g. containing either GET or POST data)\n * @param headers The headers to be sent with the request.\n * @ignore\n */\nexport const fetchWith = async <T, D = void>(input: FetchInput<D>, headers: TomTomHeaders): ParsedFetchResponse<T> => {\n const method = input.method;\n if (method === 'GET') {\n return get<T>(input.url, headers);\n }\n if (method === 'POST') {\n return post<T, D>(input, headers);\n }\n throw new Error(`Unsupported HTTP method received: ${method}`);\n};\n","import { z } from 'zod';\n\n/**\n * @ignore\n */\nexport const lineStringCoordsSchema = z\n .array(z.array(z.number()))\n .describe('Array of coordinate arrays representing a line string');\n\n/**\n * @ignore\n */\nexport const geometrySchema = z\n .object({\n type: z\n .enum([\n 'Point',\n 'MultiPoint',\n 'LineString',\n 'MultiLineString',\n 'Polygon',\n 'MultiPolygon',\n 'GeometryCollection',\n 'Circle',\n ])\n .describe('GeoJSON geometry type'),\n coordinates: z\n .union([\n z.array(z.number()),\n lineStringCoordsSchema,\n z.array(z.array(z.array(z.number()))),\n z.array(z.array(z.array(z.array(z.number())))),\n ])\n .describe('Coordinate array(s) for the geometry'),\n radius: z.optional(z.number()).describe('Radius for Circle geometries'),\n radiusMeters: z.optional(z.number()).describe('Radius in meters for Circle geometries'),\n bbox: z.optional(z.array(z.number())).describe('Bounding box [minLng, minLat, maxLng, maxLat]'),\n })\n .check(\n z.refine(\n (data) => (data.type === 'Circle' ? Boolean(data.radius) : true),\n 'type: \"Circle\" must have radius property',\n ),\n );\n\n/**\n * @ignore\n */\nexport const featureSchema = z.object({\n type: z.literal('Feature').describe('GeoJSON type identifier'),\n geometry: geometrySchema.describe('GeoJSON geometry object'),\n id: z.optional(z.union([z.string(), z.number()])).describe('Optional feature identifier'),\n properties: z.any().describe('Feature properties'),\n bbox: z.optional(z.array(z.number())).describe('Bounding box [minLng, minLat, maxLng, maxLat]'),\n});\n\n/**\n * @ignore\n */\nexport const featureCollectionSchema = z.object({\n type: z.literal('FeatureCollection').describe('GeoJSON type identifier'),\n features: z.array(featureSchema).describe('Array of GeoJSON features'),\n id: z.optional(z.union([z.string(), z.number()])).describe('Optional collection identifier'),\n properties: z.any().describe('Collection properties'),\n bbox: z.optional(z.array(z.number())).describe('Bounding box [minLng, minLat, maxLng, maxLat]'),\n});\n\n/**\n * @ignore\n */\nexport const hasLngLatSchema = z\n .union([\n z.tuple([z.number().min(-180).max(180), z.number().min(-90).max(90)]),\n z.tuple([z.number().min(-180).max(180), z.number().min(-90).max(90), z.number()]),\n z.object({\n type: z.literal('Point'),\n coordinates: z.array(z.number()),\n }),\n featureSchema,\n ])\n .describe('Geographic position as [longitude, latitude] tuple, Point geometry, or Feature');\n\n/**\n * @ignore\n */\nconst geoJsonbBoxSchema = z\n .union([\n z.array(z.number()).refine((arr) => arr.length === 4, { message: 'BBox must have 4 elements' }),\n z.array(z.number()).refine((arr) => arr.length === 6, { message: 'BBox must have 6 elements' }),\n ])\n .describe(\n 'GeoJSON bounding box array [minLng, minLat, maxLng, maxLat] or [minLng, minLat, minAlt, maxLng, maxLat, maxAlt]',\n );\n\n/**\n * @ignore\n */\nexport const geoJSONObjectSchema = z\n .union([geometrySchema, featureSchema, featureCollectionSchema])\n .describe('Any GeoJSON object (Geometry, Feature, or FeatureCollection)');\n\n/**\n * @ignore\n */\nexport const hasBBoxSchema = z\n .union([geoJsonbBoxSchema, geoJSONObjectSchema, z.array(geoJSONObjectSchema)])\n .describe('Bounding box as array, GeoJSON object, or array of GeoJSON objects');\n","import { z } from 'zod';\nimport { hasLngLatSchema } from '../shared/schema/geometriesSchema';\n\nconst autocompleteSearchRequestMandatory = z.object({\n query: z.string().describe('Partial search query for autocomplete suggestions'),\n});\n\nconst autocompleteSearchRequestOptional = z.object({\n position: hasLngLatSchema.optional().describe('Geographic position [longitude, latitude] to bias search results'),\n limit: z.number().max(100).optional().describe('Maximum number of autocomplete suggestions to return (1-100)'),\n radiusMeters: z.number().optional().describe('Search radius in meters around the specified position'),\n countries: z.array(z.string()).optional().describe('Country codes to restrict search results (ISO 3166-1 alpha-2)'),\n resultType: z.array(z.string()).optional().describe('Types of results to include in suggestions'),\n});\n\n/**\n * @ignore\n */\nexport const autocompleteSearchRequestSchema = autocompleteSearchRequestMandatory.extend(\n autocompleteSearchRequestOptional.shape,\n);\n","import type { HasLngLat, POICategory } from '@tomtom-org/maps-sdk/core';\nimport { getPosition, poiCategoriesToID } from '@tomtom-org/maps-sdk/core';\nimport { isNil } from 'lodash-es';\nimport type { CommonServiceParams } from '../serviceTypes';\n\n/**\n * @ignore\n * @param urlParams\n * @param params\n */\nexport const appendCommonParams = (urlParams: URLSearchParams, params: CommonServiceParams): void => {\n urlParams.append('apiVersion', String(params.apiVersion));\n\n // TODO: restore apiAccessToken if we implement oauth2 access:\n // if (!params.apiAccessToken) {\n urlParams.append('key', params.apiKey as string);\n // }\n\n params.language && urlParams.append('language', params.language);\n};\n\n/**\n * Adds parameter from the array by repeating each array part into a query parameter of the same name.\n * E.g. ...&avoid=motorways&avoid=ferries&...\n * @ignore\n * @param urlParams\n * @param paramName\n * @param paramArray\n */\nexport const appendByRepeatingParamName = (\n urlParams: URLSearchParams,\n paramName: string,\n paramArray?: string[],\n): void => {\n for (const param of paramArray || []) {\n urlParams.append(paramName, param);\n }\n};\n\n/**\n * @ignore\n */\nexport const appendByJoiningParamValue = (\n urlParams: URLSearchParams,\n name: string,\n values?: string[] | number[] | (string | number)[],\n): void => {\n if (Array.isArray(values) && values.length > 0) {\n urlParams.append(name, values.join(','));\n }\n};\n\n/**\n * @ignore\n */\nexport const appendOptionalParam = (\n urlParams: URLSearchParams,\n name: string,\n value?: string | number | boolean,\n): void => {\n !isNil(value) && urlParams.append(name, String(value));\n};\n\n/**\n * Adds lat and lon parameters to the url.\n * @ignore\n * @param urlParams\n * @param hasLngLat\n */\nexport const appendLatLonParamsFromPosition = (urlParams: URLSearchParams, hasLngLat: HasLngLat | undefined): void => {\n const position = getPosition(hasLngLat);\n if (position) {\n urlParams.append('lat', String(position[1]));\n urlParams.append('lon', String(position[0]));\n }\n};\n\n/**\n * map human-readable poi categories to their ID.\n * @ignore\n * @param poiCategories\n */\nexport const mapPOICategoriesToIDs = (poiCategories: (number | POICategory)[]): number[] => {\n return poiCategories.map((poiCategory) => {\n if (typeof poiCategory !== 'number') {\n return poiCategoriesToID[poiCategory];\n }\n return poiCategory;\n });\n};\n","import type { FuzzySearchParams } from '../../fuzzy-search';\nimport type { GeometrySearchParams } from '../../geometry-search';\nimport {\n appendByJoiningParamValue,\n appendCommonParams,\n appendLatLonParamsFromPosition,\n appendOptionalParam,\n mapPOICategoriesToIDs,\n} from './requestBuildingUtils';\n\n/**\n * @ignore\n */\nexport const PLACES_URL_PATH = '/maps/orbis/places';\n\n/**\n * Appends request parameters common to search APIs such as fuzzy + geometry search.\n * * Mutates the given searchURL with the appended parameters.\n * @param searchUrl The search URL to append parameters to. Should come without any parameters at this point.\n * @param params The search parameters, with global configuration already merged into them.\n */\nexport const appendCommonSearchParams = (searchUrl: URL, params: FuzzySearchParams | GeometrySearchParams): void => {\n const urlParams = searchUrl.searchParams;\n appendCommonParams(urlParams, params);\n appendOptionalParam(urlParams, 'limit', params.limit);\n appendLatLonParamsFromPosition(urlParams, params.position);\n\n appendByJoiningParamValue(urlParams, 'fuelSet', params.fuelTypes);\n appendByJoiningParamValue(urlParams, 'idxSet', params.indexes);\n appendByJoiningParamValue(urlParams, 'brandSet', params.poiBrands);\n params.poiCategories &&\n appendByJoiningParamValue(urlParams, 'categorySet', mapPOICategoriesToIDs(params.poiCategories));\n appendByJoiningParamValue(urlParams, 'connectorSet', params.connectors);\n appendByJoiningParamValue(urlParams, 'mapcodes', params.mapcodes);\n appendByJoiningParamValue(urlParams, 'extendedPostalCodesFor', params.extendedPostalCodesFor);\n\n appendOptionalParam(urlParams, 'minPowerKW', params.minPowerKW);\n appendOptionalParam(urlParams, 'maxPowerKW', params.maxPowerKW);\n appendOptionalParam(urlParams, 'view', params.view);\n appendOptionalParam(urlParams, 'openingHours', params.openingHours);\n appendOptionalParam(urlParams, 'timeZone', params.timeZone);\n appendOptionalParam(urlParams, 'relatedPois', params.relatedPois);\n appendByJoiningParamValue(urlParams, 'entityTypeSet', params.geographyTypes);\n};\n","import { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport {\n appendByJoiningParamValue,\n appendCommonParams,\n appendLatLonParamsFromPosition,\n appendOptionalParam,\n} from '../shared/request/requestBuildingUtils';\nimport type { AutocompleteSearchParams } from './types';\n\nconst buildUrlBasePath = (mergedOptions: AutocompleteSearchParams): string =>\n mergedOptions.customServiceBaseURL ||\n `${mergedOptions.commonBaseURL}${PLACES_URL_PATH}/autocomplete/${mergedOptions.query}.json`;\n\n/**\n * Default function for building autocomplete request from {@link AutocompleteSearchParams}\n * @param params The autocomplete parameters, with global configuration already merged into them.\n */\nexport const buildAutocompleteSearchRequest = (params: AutocompleteSearchParams): URL => {\n const url = new URL(`${buildUrlBasePath(params)}`);\n const urlParams = url.searchParams;\n /**\n * Auto-complete service defaults the language to en-GB if not specified explicitly as service param\n * Or global config\n */\n params.language = params.language ?? 'en-GB';\n appendCommonParams(urlParams, params);\n appendOptionalParam(urlParams, 'limit', params.limit);\n appendLatLonParamsFromPosition(urlParams, params.position);\n appendByJoiningParamValue(urlParams, 'countrySet', params.countries);\n appendOptionalParam(urlParams, 'radius', params.radiusMeters);\n appendByJoiningParamValue(urlParams, 'resultSet', params.resultType);\n\n return url;\n};\n","import type { BBox } from '@tomtom-org/maps-sdk/core';\nimport type { Position } from 'geojson';\nimport type { BoundingBoxAPI, BoundingBoxTopLeftAPI, LatLonAPI } from './types/apiPlacesResponseTypes';\n\n/**\n * @ignore\n * @param csv\n */\nexport const csvLatLngToPosition = (csv: string): Position => {\n const splitLatLng = csv.split(',');\n return [Number(splitLatLng[1]), Number(splitLatLng[0])];\n};\n\n/**\n * @ignore\n * @param position\n */\nexport const positionToCSVLatLon = (position: Position): string => `${position[1]},${position[0]}`;\n\nconst hasTopLeftPoint = (bbox: BoundingBoxAPI): bbox is BoundingBoxTopLeftAPI => {\n return (<BoundingBoxTopLeftAPI>bbox).topLeftPoint !== undefined;\n};\n\n/**\n * @ignore\n * @param apiBBox\n */\nexport const apiToGeoJSONBBox = (apiBBox: BoundingBoxAPI): BBox => {\n let westSouth: Position;\n let eastNorth: Position;\n if (hasTopLeftPoint(apiBBox)) {\n westSouth = [apiBBox.topLeftPoint.lon, apiBBox.btmRightPoint.lat];\n eastNorth = [apiBBox.btmRightPoint.lon, apiBBox.topLeftPoint.lat];\n } else {\n westSouth = csvLatLngToPosition(apiBBox.southWest);\n eastNorth = csvLatLngToPosition(apiBBox.northEast);\n }\n return [westSouth[0], westSouth[1], eastNorth[0], eastNorth[1]];\n};\n\n/**\n * @ignore\n * @param point\n */\nexport const latLonAPIToPosition = (point: LatLonAPI): Position => {\n return [point.lon, point.lat];\n};\n","import { latLonAPIToPosition } from '../shared/geometry';\nimport type { AutocompleteSearchResponse, AutocompleteSearchResponseAPI } from './types';\n\n/**\n * Default function to parse autocomplete response.\n * @param apiResponse The API response.\n */\nexport const parseAutocompleteSearchResponse = (\n apiResponse: AutocompleteSearchResponseAPI,\n): AutocompleteSearchResponse => {\n const { position, ...geoBias } = apiResponse.context.geoBias || {};\n return {\n ...apiResponse,\n context: {\n ...apiResponse.context,\n geoBias: {\n ...(position && { position: latLonAPIToPosition(position) }),\n radiusMeters: geoBias.radius,\n },\n },\n };\n};\n","import type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { autocompleteSearchRequestSchema } from './autocompleteSearchRequestSchema';\nimport { buildAutocompleteSearchRequest } from './requestBuilder';\nimport { parseAutocompleteSearchResponse } from './responseParser';\nimport type { AutocompleteSearchParams, AutocompleteSearchResponse, AutocompleteSearchResponseAPI } from './types';\n\n/**\n * Autocomplete service template type.\n * @ignore\n */\nexport type AutocompleteSearchTemplate = ServiceTemplate<\n AutocompleteSearchParams,\n URL,\n AutocompleteSearchResponseAPI,\n AutocompleteSearchResponse\n>;\n\n/**\n * Autocomplete service template main implementation.\n * @ignore\n */\nexport const autocompleteSearchTemplate: AutocompleteSearchTemplate = {\n requestValidation: { schema: autocompleteSearchRequestSchema },\n buildRequest: buildAutocompleteSearchRequest,\n sendRequest: get,\n parseResponse: parseAutocompleteSearchResponse,\n};\n","import { callService } from '../shared/serviceTemplate';\nimport type { AutocompleteSearchTemplate } from './autocompleteSearchTemplate';\nimport { autocompleteSearchTemplate } from './autocompleteSearchTemplate';\nimport type { AutocompleteSearchParams, AutocompleteSearchResponse } from './types';\n\n/**\n * Autocomplete search queries as the user types, enabling faster and more accurate search.\n *\n * The Autocomplete service recognizes entities (places, addresses, POIs) within a partial\n * input query and offers them as completion suggestions. This enables real-time search\n * assistance and improves the search experience.\n *\n * @remarks\n * Key features:\n * - **Real-time suggestions**: Returns results as the user types\n * - **Entity recognition**: Identifies addresses, POIs, and geographic areas\n * - **Structured results**: Provides both plain text and structured data\n * - **Query refinement**: Helps users formulate more accurate search queries\n * - **Fast response**: Optimized for low-latency interactive use\n *\n * Typical use cases:\n * - Search box autocomplete dropdowns\n * - Address entry forms\n * - Location pickers\n * - Navigation apps\n *\n * @param params - Autocomplete parameters including the partial query\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to autocomplete suggestions\n *\n * @example\n * ```typescript\n * // Autocomplete as user types \"amster\"\n * const suggestions = await autocompleteSearch({\n * key: 'your-api-key',\n * query: 'amster',\n * limit: 5\n * });\n * // Returns: Amsterdam, Amsterdam Centraal, etc.\n *\n * // Autocomplete with position bias\n * const localSuggestions = await autocompleteSearch({\n * key: 'your-api-key',\n * query: 'main st',\n * at: [4.9041, 52.3676], // Near Amsterdam\n * limit: 10\n * });\n *\n * // Autocomplete with category filter\n * const restaurantSuggestions = await autocompleteSearch({\n * key: 'your-api-key',\n * query: 'pizz',\n * categorySet: [7315], // Restaurant category\n * at: [4.9041, 52.3676]\n * });\n * ```\n *\n * @see [Autocomplete API Documentation](https://docs.tomtom.com/search-api/documentation/autocomplete-service/autocomplete)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Search Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/search)\n *\n * @group Autocomplete Search\n */\nexport const autocompleteSearch = async (\n params: AutocompleteSearchParams,\n customTemplate?: Partial<AutocompleteSearchTemplate>,\n): Promise<AutocompleteSearchResponse> =>\n callService(params, { ...autocompleteSearchTemplate, ...customTemplate }, 'Autocomplete');\n\nexport default autocompleteSearch;\n","import { autocompleteSearch } from './autocompleteSearch';\nimport type { AutocompleteSearchTemplate } from './autocompleteSearchTemplate';\nimport { autocompleteSearchTemplate } from './autocompleteSearchTemplate';\nimport { buildAutocompleteSearchRequest } from './requestBuilder';\nimport { parseAutocompleteSearchResponse } from './responseParser';\n\nconst customize: {\n autocompleteSearch: typeof autocompleteSearch;\n buildAutocompleteSearchRequest: typeof buildAutocompleteSearchRequest;\n parseAutocompleteSearchResponse: typeof parseAutocompleteSearchResponse;\n autocompleteSearchTemplate: AutocompleteSearchTemplate;\n} = {\n autocompleteSearch,\n buildAutocompleteSearchRequest,\n parseAutocompleteSearchResponse,\n autocompleteSearchTemplate,\n};\nexport default customize;\n","import { z } from 'zod';\nimport { commonServiceRequestSchema } from '../shared/schema/commonParamsSchema';\n\n/**\n * @ignore\n */\nexport const evChargingStationsAvailabilityRequestSchema = commonServiceRequestSchema.extend({\n id: z.string().describe('Unique identifier of the EV charging station'),\n});\n","import { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport { appendCommonParams } from '../shared/request/requestBuildingUtils';\nimport type { ChargingStationsAvailabilityParams } from './types/evChargingStationsAvailabilityParams';\n\nconst buildUrlBasePath = (params: ChargingStationsAvailabilityParams): string =>\n params.customServiceBaseURL ?? `${params.commonBaseURL}${PLACES_URL_PATH}/ev/id`;\n\n/**\n * Default method for building ev charging stations availability request from {@link ChargingStationsAvailabilityParams}\n * @param params The charging availability parameters, with global configuration already merged into them.\n */\nexport const buildEVChargingStationsAvailabilityRequest = (params: ChargingStationsAvailabilityParams): URL => {\n const url = new URL(buildUrlBasePath(params));\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n urlParams.append('id', params.id);\n return url;\n};\n","import { ChargingSpeed } from '@tomtom-org/maps-sdk/core';\n\n/**\n * @ignore\n */\nexport const toChargingSpeed = (powerInKW: number): ChargingSpeed => {\n if (powerInKW < 12) {\n return 'slow';\n } else if (powerInKW < 50) {\n return 'regular';\n } else if (powerInKW < 150) {\n return 'fast';\n }\n return 'ultra-fast';\n};\n","import type {\n ChargingPointAvailability,\n ChargingPointStatus,\n ChargingStation,\n Connector,\n ConnectorAvailability,\n ConnectorCount,\n} from '@tomtom-org/maps-sdk/core';\n\n/**\n * @ignore\n */\nexport const toChargingPointAvailability = (chargingStations: ChargingStation[]): ChargingPointAvailability => {\n const availability: ChargingPointAvailability = { count: 0, statusCounts: {} };\n for (const station of chargingStations) {\n for (const chargingPoint of station.chargingPoints) {\n availability.count++;\n availability.statusCounts[chargingPoint.status] =\n (availability.statusCounts[chargingPoint.status] || 0) + 1;\n }\n }\n return availability;\n};\n\n// Two connectors can be considered equal when they have the same type and power:\nconst areEqual = (connectorA: Connector, connectorB: Connector) =>\n connectorA.type === connectorB.type && connectorA.ratedPowerKW === connectorB.ratedPowerKW;\n\nconst addConnectorCount = (\n connectors: Connector[] | undefined,\n counts: ConnectorCount[], // we are mutating this input\n): void => {\n if (!connectors) {\n // defensive check, sometimes connectors are undefined\n return;\n }\n for (const connector of connectors) {\n const existingCount = counts.find((connectorCount) => areEqual(connector, connectorCount.connector));\n if (existingCount) {\n existingCount.count++;\n } else {\n // new count entry:\n counts.push({ connector, count: 1 });\n }\n }\n};\n\nconst addConnectorCountAndStatus = (\n connectors: Connector[] | undefined,\n status: ChargingPointStatus | undefined,\n availabilities: ConnectorAvailability[], // we are mutating this input\n): void => {\n if (!connectors) {\n // defensive check, sometimes connectors are undefined\n return;\n }\n for (const connector of connectors) {\n const existingAvailability = availabilities.find((connectorAvailability) =>\n areEqual(connector, connectorAvailability.connector),\n );\n if (existingAvailability) {\n existingAvailability.count++;\n if (status) {\n // we're mutating the input object here:\n const statusCounts = existingAvailability.statusCounts;\n existingAvailability.statusCounts[status] = (statusCounts[status] || 0) + 1;\n }\n } else {\n // new availability entry:\n availabilities.push({ connector, count: 1, statusCounts: status ? { [status]: 1 } : {} });\n }\n }\n};\n\n/**\n * @ignore\n */\nexport const toConnectorCounts = (connectors: Connector[]): ConnectorCount[] => {\n const availabilities: ConnectorAvailability[] = [];\n addConnectorCount(connectors, availabilities);\n return availabilities;\n};\n\n/**\n * @ignore\n */\nexport const toConnectorBasedAvailabilities = (chargingStations: ChargingStation[]): ConnectorAvailability[] => {\n const availabilities: ConnectorAvailability[] = [];\n for (const station of chargingStations) {\n for (const chargingPoint of station.chargingPoints) {\n addConnectorCountAndStatus(chargingPoint.connectors, chargingPoint.status, availabilities);\n }\n }\n return availabilities;\n};\n","import type { Moment, OpeningHours, Place, SearchPlaceProps, TimeRange } from '@tomtom-org/maps-sdk/core';\nimport { toPointGeometry } from '@tomtom-org/maps-sdk/core';\nimport { omit } from 'lodash-es';\nimport { toConnectorCounts } from '../ev-charging-stations-availability/connectorAvailability';\nimport { toChargingSpeed } from './ev';\nimport { apiToGeoJSONBBox, latLonAPIToPosition } from './geometry';\nimport type {\n BrandAPI,\n CommonSearchPlaceResultAPI,\n MomentAPI,\n OpeningHoursAPI,\n SummaryAPI,\n} from './types/apiPlacesResponseTypes';\nimport type { SearchSummary } from './types/searchSummary';\n\nconst parseYyyymmddDate = (dateYyyymmdd: string): { year: number; month: number; day: number } => {\n const splitDate = dateYyyymmdd.split('-');\n return {\n year: Number.parseInt(splitDate[0]),\n month: Number.parseInt(splitDate[1]),\n day: Number.parseInt(splitDate[2]),\n };\n};\n\nconst parseMoment = (momentApi: MomentAPI): Moment => {\n const { year, month, day } = parseYyyymmddDate(momentApi.date);\n return {\n dateYYYYMMDD: momentApi.date,\n year,\n month,\n day,\n hour: momentApi.hour,\n minute: momentApi.minute,\n date: new Date(year, month - 1, day, momentApi.hour, momentApi.minute),\n };\n};\n\nconst alwaysOpenInThisPeriod = (timeRanges: TimeRange[]): boolean =>\n timeRanges.length === 1 && timeRanges[0].start.hour === 0 && timeRanges[0].end.hour === 0;\n\n/**\n * @ignore\n */\nexport const parseOpeningHours = (openingHoursApi: OpeningHoursAPI): OpeningHours => {\n const timeRanges = openingHoursApi.timeRanges.map(\n (timeRangeApi): TimeRange => ({\n start: parseMoment(timeRangeApi.startTime),\n end: parseMoment(timeRangeApi.endTime),\n }),\n );\n return {\n mode: openingHoursApi.mode,\n timeRanges,\n alwaysOpenThisPeriod: alwaysOpenInThisPeriod(timeRanges),\n };\n};\n\n/**\n * Shared response parsing between geometry search and place by id service.\n * @ignore\n */\nexport const parseSearchAPIResult = (result: CommonSearchPlaceResultAPI): Place<SearchPlaceProps> => {\n const { position, entryPoints, poi, id, dist, boundingBox, chargingPark, ...rest } = result;\n const connectors = chargingPark?.connectors?.map((connector) => ({\n ...omit(connector, 'connectorType'),\n type: connector.connectorType,\n chargingSpeed: toChargingSpeed(connector.ratedPowerKW),\n }));\n return {\n type: 'Feature',\n geometry: toPointGeometry(latLonAPIToPosition(position)),\n ...(boundingBox && { bbox: apiToGeoJSONBBox(boundingBox) }),\n id,\n properties: {\n ...omit(rest, 'viewport'),\n ...(dist && { distance: dist }),\n ...(entryPoints?.length && {\n entryPoints: entryPoints.map((entrypoint) => ({\n ...entrypoint,\n position: latLonAPIToPosition(entrypoint.position),\n })),\n }),\n ...(connectors?.length && {\n chargingPark: {\n ...chargingPark,\n connectors: toConnectorCounts(connectors),\n },\n }),\n ...(poi && {\n poi: {\n ...omit(poi, 'categorySet', 'openingHours'),\n brands: poi?.brands?.map((brand: BrandAPI) => brand.name) ?? [],\n categoryIds: poi?.categorySet?.map((category) => category.id) ?? [],\n ...(poi?.openingHours && { openingHours: parseOpeningHours(poi?.openingHours) }),\n },\n }),\n },\n };\n};\n\n/**\n * @ignore\n */\nexport const parseSummaryAPI = (summary: SummaryAPI): SearchSummary => {\n const { geoBias, ...rest } = summary;\n\n return {\n ...(geoBias && { geoBias: latLonAPIToPosition(geoBias) }),\n ...rest,\n };\n};\n","import type { ChargingStation, ChargingStationsAvailability } from '@tomtom-org/maps-sdk/core';\nimport { toChargingSpeed } from '../shared/ev';\nimport { parseOpeningHours } from '../shared/searchResultParsing';\nimport { toChargingPointAvailability, toConnectorBasedAvailabilities } from './connectorAvailability';\nimport type { ChargingStationsAvailabilityResponseAPI } from './types/apiTypes';\n\nconst toChargingPointStations = (stations: ChargingStation[]) =>\n stations.map((station) => ({\n ...station,\n chargingPoints: station.chargingPoints.map((chargingPoint) => ({\n ...chargingPoint,\n connectors: chargingPoint.connectors?.map((connector) => ({\n ...connector,\n chargingSpeed: toChargingSpeed(connector.ratedPowerKW),\n })),\n })),\n }));\n\n/**\n * Default method for parsing ev charging stations availability from {@link ChargingStationsAvailability}\n * @param apiResponse\n */\nexport const parseEVChargingStationsAvailabilityResponse = (\n apiResponse: ChargingStationsAvailabilityResponseAPI,\n): ChargingStationsAvailability | undefined => {\n const result = apiResponse.results?.[0];\n return result\n ? {\n id: result.id,\n accessType: result.accessType,\n chargingStations: toChargingPointStations(result.chargingStations),\n chargingPointAvailability: toChargingPointAvailability(result.chargingStations),\n connectorAvailabilities: toConnectorBasedAvailabilities(result.chargingStations),\n ...(result.openingHours && { openingHours: parseOpeningHours(result.openingHours) }),\n }\n : undefined;\n};\n","import type { ChargingStationsAvailability } from '@tomtom-org/maps-sdk/core';\nimport type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { evChargingStationsAvailabilityRequestSchema } from './evChargingStationsAvailabilityRequestSchema';\nimport { parseEVChargingStationsAvailabilityResponseError } from './evChargingStationsAvailabilityResponseErrorParser';\nimport { buildEVChargingStationsAvailabilityRequest } from './requestBuilder';\nimport { parseEVChargingStationsAvailabilityResponse } from './responseParser';\nimport type { ChargingStationsAvailabilityResponseAPI } from './types/apiTypes';\nimport type { ChargingStationsAvailabilityParams } from './types/evChargingStationsAvailabilityParams';\n\n/**\n * EV Charging Stations Availability service template type.\n * @ignore\n */\nexport type EVChargingStationsAvailabilityTemplate = ServiceTemplate<\n ChargingStationsAvailabilityParams,\n URL,\n ChargingStationsAvailabilityResponseAPI,\n ChargingStationsAvailability | undefined\n>;\n\n/**\n * EV Charging Stations Availability service template main implementation.\n * @ignore\n */\nexport const evChargingStationsAvailabilityTemplate: EVChargingStationsAvailabilityTemplate = {\n requestValidation: { schema: evChargingStationsAvailabilityRequestSchema },\n buildRequest: buildEVChargingStationsAvailabilityRequest,\n sendRequest: get,\n parseResponse: parseEVChargingStationsAvailabilityResponse,\n parseResponseError: parseEVChargingStationsAvailabilityResponseError,\n};\n","import type { ParseResponseError } from '../shared';\nimport { SDKServiceError } from '../shared';\n\n/**\n * @ignore\n * @param apiError\n * @param serviceName\n */\nexport const parseEVChargingStationsAvailabilityResponseError: ParseResponseError = (apiError, serviceName) => {\n const errorMessage = apiError.data?.detailedError?.message ?? apiError.message;\n return new SDKServiceError(errorMessage, serviceName, apiError.status);\n};\n","import type { EVChargingStationsAvailabilityTemplate } from './evChargingStationsAvailabilityTemplate';\nimport { evChargingStationsAvailabilityTemplate } from './evChargingStationsAvailabilityTemplate';\nimport { buildEVChargingStationsAvailabilityRequest } from './requestBuilder';\nimport { parseEVChargingStationsAvailabilityResponse } from './responseParser';\n\nconst customize: {\n buildEVChargingStationsAvailabilityRequest: typeof buildEVChargingStationsAvailabilityRequest;\n parseEVChargingStationsAvailabilityResponse: typeof parseEVChargingStationsAvailabilityResponse;\n evChargingStationsAvailabilityTemplate: EVChargingStationsAvailabilityTemplate;\n} = {\n buildEVChargingStationsAvailabilityRequest,\n parseEVChargingStationsAvailabilityResponse,\n evChargingStationsAvailabilityTemplate,\n};\nexport default customize;\n","import { z } from 'zod';\nimport { hasBBoxSchema } from './geometriesSchema';\n\n/**\n * @ignore\n */\nexport const commonGeocodeAndFuzzySearchParamsSchema = z.object({\n typeahead: z.boolean().optional().describe('Enable predictive/autocomplete mode for partial input queries'),\n offset: z\n .number()\n .max(1900)\n .optional()\n .describe('Starting position within result set for pagination (zero-based index)'),\n radiusMeters: z.number().optional().describe('Search radius in meters around the specified position'),\n boundingBox: hasBBoxSchema.optional().describe('Bounding box to constrain search results to a rectangular area'),\n countries: z.array(z.string()).optional().describe('Country codes to restrict search results (ISO 3166-1 alpha-2)'),\n});\n","import { views } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { hasLngLatSchema } from './geometriesSchema';\n\nconst placesParamsMandatory = z.object({\n query: z.string().describe('Search query for places, addresses, or locations'),\n});\n\nconst placesParamsOptional = z.object({\n position: hasLngLatSchema.optional().describe('Geographic position [longitude, latitude] to bias search results'),\n limit: z.number().max(100).optional().describe('Maximum number of results to return (1-100)'),\n extendedPostalCodesFor: z\n .array(z.string())\n .optional()\n .describe('Indexes for which to include extended postal codes in results'),\n mapcodes: z\n .array(z.string())\n .optional()\n .describe('Request mapcode representations for locations (Local, International, Alternative)'),\n view: z.enum(views).optional().describe('Geopolitical view for disputed territories'),\n geographyTypes: z\n .array(z.string())\n .optional()\n .describe('Filter results to specific geography types (Country, Municipality, etc.)'),\n});\n\n/**\n * @ignore\n */\nexport const commonPlacesParamsSchema = placesParamsMandatory.extend(placesParamsOptional.shape);\n","import { commonGeocodeAndFuzzySearchParamsSchema } from '../shared/schema/commonGeocodeAndFuzzySearchParamsSchema';\nimport { commonServiceRequestSchema } from '../shared/schema/commonParamsSchema';\nimport { commonPlacesParamsSchema } from '../shared/schema/commonPlacesParamsSchema';\n\n/**\n * @ignore\n */\nexport const geocodingRequestSchema = commonServiceRequestSchema\n .extend(commonPlacesParamsSchema.shape)\n .extend(commonGeocodeAndFuzzySearchParamsSchema.shape);\n","/**\n * @ignore\n * @param input\n */\nexport const arrayToCSV = (input: unknown | unknown[]): string =>\n !input ? '' : Array.isArray(input) ? input.join(',') : typeof input === 'string' ? input : String(input);\n\n/**\n * Samples, if necessary, the given array to fit within the given max length.\n * * If the array already fits within maxLength, the same array is returned.\n * * The sampling is done by spreading the array points at a constant increment.\n * * The first and last points are always included if array and max lengths are > 1.\n * * The sampling is done with speed in mind, so it's not guaranteed to always fit maxLength. Very often it will be shorter.\n *\n * Use this when needing to quickly simplify an array to fit some max length without caring too much on the lost detail.\n * * If both the array and max length are long enough, the loss of detail won't likely be an issue.\n * @ignore\n */\nexport const sampleWithinMaxLength = <T>(array: T[], maxLength: number): T[] => {\n const length = array.length;\n if (length <= maxLength) {\n return array;\n }\n\n const sampledArray = [];\n let i;\n const increment = Math.ceil(length / maxLength);\n for (i = 0; i < length; i += increment) {\n sampledArray.push(array[i]);\n }\n // ensuring the last point is always added:\n if (maxLength > 1 && i >= length - increment) {\n if (sampledArray.length < maxLength) {\n sampledArray.push(array[length - 1]);\n } else {\n sampledArray[sampledArray.length - 1] = array[length - 1];\n }\n }\n\n return sampledArray;\n};\n","import { bboxFromGeoJSON } from '@tomtom-org/maps-sdk/core';\nimport { isNil } from 'lodash-es';\nimport { arrayToCSV } from '../shared/arrays';\nimport { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport { appendCommonParams, appendLatLonParamsFromPosition } from '../shared/request/requestBuildingUtils';\nimport type { GeocodingParams } from './types/geocodingParams';\n\nconst buildUrlBasePath = (params: GeocodingParams): string =>\n params.customServiceBaseURL || `${params.commonBaseURL}${PLACES_URL_PATH}/geocode`;\n\n/**\n * Default method for building geocoding request from {@link GeocodingParams}\n * @param params The geocoding parameters, with global configuration already merged into them.\n */\nexport const buildGeocodingRequest = (params: GeocodingParams): URL => {\n const url = new URL(`${buildUrlBasePath(params)}/${params.query}.json`);\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n // geocoding specific parameters:\n params.typeahead && urlParams.append('typeahead', String(params.typeahead));\n !isNil(params.limit) && urlParams.append('limit', String(params.limit));\n !isNil(params.offset) && urlParams.append('ofs', String(params.offset));\n appendLatLonParamsFromPosition(urlParams, params.position);\n params.countries && urlParams.append('countrySet', arrayToCSV(params.countries));\n !isNil(params.radiusMeters) && urlParams.append('radius', String(params.radiusMeters));\n const bbox = params.boundingBox && bboxFromGeoJSON(params.boundingBox);\n if (bbox) {\n urlParams.append('topLeft', arrayToCSV([bbox[3], bbox[0]]));\n urlParams.append('btmRight', arrayToCSV([bbox[1], bbox[2]]));\n }\n params.extendedPostalCodesFor &&\n urlParams.append('extendedPostalCodesFor', arrayToCSV(params.extendedPostalCodesFor));\n params.mapcodes && urlParams.append('mapcodes', arrayToCSV(params.mapcodes));\n params.view && urlParams.append('view', params.view);\n params.geographyTypes && urlParams.append('entityTypeSet', arrayToCSV(params.geographyTypes));\n return url;\n};\n","import type { GeographyType, Place } from '@tomtom-org/maps-sdk/core';\nimport { bboxFromGeoJSON, bboxOnlyIfWithArea, toPointGeometry } from '@tomtom-org/maps-sdk/core';\nimport { omit } from 'lodash-es';\nimport { apiToGeoJSONBBox, latLonAPIToPosition } from '../shared/geometry';\nimport type { GeocodingResponseAPI, GeocodingResultAPI } from './types/apiTypes';\nimport type { GeocodingProps, GeocodingResponse } from './types/geocodingResponse';\n\nconst parseApiResult = (result: GeocodingResultAPI): Place<GeocodingProps> => {\n const { position, boundingBox, dist, entryPoints, addressRanges, entityType, id, ...rest } = result;\n\n return {\n type: 'Feature',\n geometry: toPointGeometry(latLonAPIToPosition(position)),\n ...(boundingBox && { bbox: apiToGeoJSONBBox(boundingBox) }),\n id,\n properties: {\n ...omit(rest, 'viewport'),\n ...(dist && { distance: dist }),\n ...(entityType && { geographyType: entityType.split(',') as GeographyType[] }),\n ...(entryPoints && {\n entryPoints: entryPoints.map((entrypoint) => ({\n ...entrypoint,\n position: latLonAPIToPosition(entrypoint.position),\n })),\n }),\n ...(addressRanges && {\n addressRanges: {\n ...addressRanges,\n from: latLonAPIToPosition(addressRanges.from),\n to: latLonAPIToPosition(addressRanges.to),\n },\n }),\n },\n };\n};\n\n/**\n * Default method for parsing geocoding request from {@link GeocodingResponse}\n * @param apiResponse\n */\nexport const parseGeocodingResponse = (apiResponse: GeocodingResponseAPI): GeocodingResponse => {\n const results = apiResponse.results;\n const features = results.map(parseApiResult);\n const bbox = bboxOnlyIfWithArea(bboxFromGeoJSON(features));\n return {\n type: 'FeatureCollection',\n features,\n ...(bbox && { bbox }),\n };\n};\n","import type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { geocodingRequestSchema } from './geocodingRequestSchema';\nimport { buildGeocodingRequest } from './requestBuilder';\nimport { parseGeocodingResponse } from './responseParser';\nimport type { GeocodingResponseAPI } from './types/apiTypes';\nimport type { GeocodingParams } from './types/geocodingParams';\nimport type { GeocodingResponse } from './types/geocodingResponse';\n\n/**\n * Geocoding service template type.\n * @ignore\n */\nexport type GeocodingTemplate = ServiceTemplate<GeocodingParams, URL, GeocodingResponseAPI, GeocodingResponse>;\n\n/**\n * Geocoding service template main implementation.\n * @ignore\n */\nexport const geocodingTemplate: GeocodingTemplate = {\n requestValidation: { schema: geocodingRequestSchema },\n buildRequest: buildGeocodingRequest,\n sendRequest: get,\n parseResponse: parseGeocodingResponse,\n};\n","import type { GeocodingTemplate } from './geocodingTemplate';\nimport { geocodingTemplate } from './geocodingTemplate';\nimport { buildGeocodingRequest } from './requestBuilder';\nimport { parseGeocodingResponse } from './responseParser';\n\nconst customize: {\n buildGeocodingRequest: typeof buildGeocodingRequest;\n parseGeocodingResponse: typeof parseGeocodingResponse;\n geocodingTemplate: GeocodingTemplate;\n} = {\n buildGeocodingRequest,\n parseGeocodingResponse,\n geocodingTemplate,\n};\nexport default customize;\n","import { z } from 'zod';\nimport { featureCollectionSchema, featureSchema } from '../shared/schema/geometriesSchema';\n\nconst geometryDataRequestMandatory = z.object({\n geometries: z\n .union([\n featureCollectionSchema,\n z\n .array(z.union([z.string(), featureSchema]))\n .min(1)\n .max(20),\n ])\n .describe('GeoJSON FeatureCollection or array of geometry IDs/Features (max 20)'),\n});\n\nconst geometryDataRequestOptional = z.object({\n zoom: z.number().min(0).max(22).optional().describe('Zoom level for geometry data simplification (0-22)'),\n});\n\nexport const geometryDataRequestSchema = geometryDataRequestMandatory.extend(geometryDataRequestOptional.shape);\n","import type { Place, Places } from '@tomtom-org/maps-sdk/core';\nimport { arrayToCSV } from '../shared/arrays';\nimport { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport { appendOptionalParam } from '../shared/request/requestBuildingUtils';\nimport type { GeometriesInput, GeometryParams } from './types/geometryDataParams';\n\nconst buildUrlBasePath = (params: GeometryParams): string =>\n params.customServiceBaseURL || `${params.commonBaseURL}${PLACES_URL_PATH}/additionalData.json`;\n\nconst getGeometryIDs = (placesArray: Place[]): string[] =>\n placesArray.map((place) => place.properties.dataSources?.geometry?.id as string).filter((id) => id);\n\n// (@see geometryDataRequestSchema)\nconst appendGeometries = (urlParams: URLSearchParams, geometries: GeometriesInput | Places | Place[]): void => {\n let geometryIDs: string[];\n\n if (Array.isArray(geometries)) {\n // (assuming min and max length already validated)\n if (typeof geometries[0] === 'string') {\n geometryIDs = geometries as string[];\n } else {\n geometryIDs = getGeometryIDs(geometries as Place[]);\n }\n } else {\n // (assuming already validated as FeatureCollection)\n geometryIDs = getGeometryIDs(geometries.features);\n }\n\n urlParams.append('geometries', arrayToCSV(geometryIDs));\n};\n\n/**\n * Default function for building a geometry data request from {@link GeometryDataParams}\n * @param params The geometry data parameters, with global configuration already merged into them.\n */\nexport const buildGeometryDataRequest = (params: GeometryParams): URL => {\n const url = new URL(buildUrlBasePath(params));\n const urlParams = url.searchParams;\n // (no language in this service)\n urlParams.append('apiVersion', String(params.apiVersion));\n urlParams.append('key', params.apiKey as string);\n appendGeometries(urlParams, params.geometries);\n appendOptionalParam(urlParams, 'geometriesZoom', params.zoom);\n return url;\n};\n","import { bboxFromGeoJSON, generateId, PolygonFeature, PolygonFeatures } from '@tomtom-org/maps-sdk/core';\nimport type { GeometryDataResponseAPI } from './types/apiTypes';\n\n/**\n * Default geometry data API response parsing.\n * * The API response consists of an array, with a FeatureCollection (with only one feature) for each geometry.\n * * The parsed response consists of a fully-GeoJSON-compatible FeatureCollection with a Feature for each geometry.\n * * Each geometry ID is included in each GeoJSON feature \"id\" field.\n * @param apiResponse\n */\nexport const parseGeometryDataResponse = (apiResponse: GeometryDataResponseAPI): PolygonFeatures => {\n const features = apiResponse.additionalData\n .flatMap((data) =>\n (data.geometryData as PolygonFeatures)?.features.map((feature) => ({\n ...feature,\n id: feature.id ?? generateId(),\n bbox: bboxFromGeoJSON(feature.geometry),\n })),\n )\n .filter((feature) => feature) as PolygonFeature[];\n return {\n type: 'FeatureCollection',\n bbox: bboxFromGeoJSON(features),\n features,\n };\n};\n","import type { PolygonFeatures } from '@tomtom-org/maps-sdk/core';\nimport type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { geometryDataRequestSchema } from './geometryDataRequestSchema';\nimport { buildGeometryDataRequest } from './requestBuilder';\nimport { parseGeometryDataResponse } from './responseParser';\nimport type { GeometryDataResponseAPI } from './types/apiTypes';\nimport type { GeometryParams } from './types/geometryDataParams';\n\n/**\n * @ignore\n */\nexport type GeometryDataTemplate = ServiceTemplate<GeometryParams, URL, GeometryDataResponseAPI, PolygonFeatures>;\n\n/**\n * @ignore\n */\nexport const geometryDataTemplate: GeometryDataTemplate = {\n requestValidation: { schema: geometryDataRequestSchema },\n buildRequest: buildGeometryDataRequest,\n sendRequest: get,\n parseResponse: parseGeometryDataResponse,\n};\n","import type { GeometryDataTemplate } from './geometryDataTemplate';\nimport { geometryDataTemplate } from './geometryDataTemplate';\nimport { buildGeometryDataRequest } from './requestBuilder';\nimport { parseGeometryDataResponse } from './responseParser';\n\nconst customize: {\n buildGeometryDataRequest: typeof buildGeometryDataRequest;\n parseGeometryDataResponse: typeof parseGeometryDataResponse;\n geometryDataTemplate: GeometryDataTemplate;\n} = {\n buildGeometryDataRequest,\n parseGeometryDataResponse,\n geometryDataTemplate,\n};\nexport default customize;\n","import { poiCategoriesToID } from '@tomtom-org/maps-sdk/core';\nimport { type ZodObject, z } from 'zod';\nimport { commonPlacesParamsSchema } from '../shared/schema/commonPlacesParamsSchema';\n\nconst poiCategoriesToIdZodObject = z.object(poiCategoriesToID) as unknown as ZodObject<any>;\n\nconst searchExtraParamsOptional = z.object({\n indexes: z.array(z.string()).optional().describe('Search indexes to query (Geo, PAD, Addr, Str, XStr, POI)'),\n poiCategories: z\n .array(z.union([z.number(), z.keyof(poiCategoriesToIdZodObject)]))\n .optional()\n .describe('Filter results to specific POI categories'),\n poiBrands: z.array(z.string()).optional().describe('Filter results to specific POI brands'),\n connectors: z.array(z.string()).optional().describe('Filter EV charging stations by connector types'),\n fuelTypes: z.array(z.string()).optional().describe('Filter fuel stations by available fuel types'),\n openingHours: z.string().optional().describe('Request opening hours information for POIs'),\n timeZone: z.string().optional().describe('Request timezone information for POI locations (iana)'),\n relatedPois: z.string().optional().describe('Related POI inclusion mode (off, child, parent, all)'),\n minPowerKW: z.number().optional().describe('Minimum charging power in kilowatts for EV charging stations'),\n maxPowerKW: z.number().optional().describe('Maximum charging power in kilowatts for EV charging stations'),\n minFuzzyLevel: z.number().optional().describe('Minimum fuzzy matching level (1-4)'),\n mixFuzzyLevel: z.number().optional().describe('Maximum fuzzy matching level (1-4)'),\n});\n\n/**\n * @ignore\n */\nexport const commonSearchParamsSchema = commonPlacesParamsSchema.extend(searchExtraParamsOptional.shape);\n","import { z } from 'zod';\nimport { commonSearchParamsSchema } from '../search/commonSearchParamsSchema';\nimport { featureCollectionSchema, geometrySchema } from '../shared/schema/geometriesSchema';\n\nconst geometrySearchRequestMandatory = z.object({\n geometries: z\n .array(z.union([featureCollectionSchema, geometrySchema]))\n .describe('Array of GeoJSON geometries or FeatureCollections to search within'),\n});\n\n/**\n * @ignore\n */\nexport const geometrySearchRequestSchema = commonSearchParamsSchema.extend(geometrySearchRequestMandatory.shape);\n","import { bboxFromCoordsArray } from '@tomtom-org/maps-sdk/core';\nimport type { MultiPolygon, Position } from 'geojson';\nimport type { PostObject } from '../shared';\nimport { sampleWithinMaxLength } from '../shared/arrays';\nimport { positionToCSVLatLon } from '../shared/geometry';\nimport { appendCommonSearchParams, PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport type { GeometryAPI, GeometrySearchParams, GeometrySearchPayloadAPI, SearchGeometryInput } from './types';\n\nconst findFiftyLargestPolygons = (searchGeometry: MultiPolygon): Position[][][] => {\n // we calculate the size of each polygon based on bounding box (simplified)\n // we put it into a map for easy sorting\n // we sort the map by using size and keep only 50 largest polygons\n let polygonSizeMap = new Map<Position[][], number>();\n searchGeometry.coordinates.forEach((polygon) => {\n const bboxOfPolygon = bboxFromCoordsArray(polygon[0]);\n if (bboxOfPolygon) {\n const polygonSize = Math.abs((bboxOfPolygon[2] - bboxOfPolygon[0]) * (bboxOfPolygon[3] - bboxOfPolygon[1]));\n polygonSizeMap.set(polygon, polygonSize);\n }\n });\n polygonSizeMap = new Map([...polygonSizeMap.entries()].sort((a, b) => b[1] - a[1]).splice(0, 50));\n return [...polygonSizeMap.keys()];\n};\n\nconst sdkGeometryToApiGeometries = (searchGeometry: SearchGeometryInput): GeometryAPI[] => {\n switch (searchGeometry.type) {\n case 'Circle':\n return [\n {\n type: 'CIRCLE',\n radius: searchGeometry.radius,\n position: positionToCSVLatLon(searchGeometry.coordinates),\n },\n ];\n case 'Polygon':\n return [\n {\n type: 'POLYGON',\n vertices: sampleWithinMaxLength(searchGeometry.coordinates[0], 50).map((coord) =>\n positionToCSVLatLon(coord),\n ),\n },\n ];\n case 'MultiPolygon': {\n if (searchGeometry.coordinates.length > 50) {\n // we have too many polygons for the service to work\n return findFiftyLargestPolygons(searchGeometry).flatMap((polygonCoords) =>\n sdkGeometryToApiGeometries({ type: 'Polygon', coordinates: polygonCoords }),\n );\n }\n return searchGeometry.coordinates.flatMap((polygonCoords) =>\n sdkGeometryToApiGeometries({ type: 'Polygon', coordinates: polygonCoords }),\n );\n }\n case 'FeatureCollection':\n return searchGeometry.features.flatMap((feature) => sdkGeometryToApiGeometries(feature.geometry));\n default:\n // @ts-ignore\n throw new Error(`Type ${(searchGeometry as unknown).type} is not supported`);\n }\n};\n\nconst buildUrlBasePath = (mergedOptions: GeometrySearchParams): string =>\n mergedOptions.customServiceBaseURL ??\n `${mergedOptions.commonBaseURL}${PLACES_URL_PATH}/geometrySearch/${mergedOptions.query}.json`;\n\n/**\n * Default function for building a geometry search request from {@link GeometrySearchParams}\n * @param params The geometry search parameters, with global configuration already merged into them.\n */\nexport const buildGeometrySearchRequest = (params: GeometrySearchParams): PostObject<GeometrySearchPayloadAPI> => {\n const url = new URL(`${buildUrlBasePath(params)}`);\n appendCommonSearchParams(url, params);\n\n return {\n url,\n data: {\n geometryList: params.geometries.flatMap(sdkGeometryToApiGeometries),\n },\n };\n};\n","import { bboxFromGeoJSON, bboxOnlyIfWithArea } from '@tomtom-org/maps-sdk/core';\nimport { parseSearchAPIResult, parseSummaryAPI } from '../shared/searchResultParsing';\nimport type { GeometrySearchResponse, GeometrySearchResponseAPI } from './types';\n\n/**\n * Default function to parse a geometry search response.\n * @param apiResponse The API response.\n */\nexport const parseGeometrySearchResponse = (apiResponse: GeometrySearchResponseAPI): GeometrySearchResponse => {\n const features = apiResponse.results.map(parseSearchAPIResult);\n const bbox = bboxOnlyIfWithArea(bboxFromGeoJSON(features));\n return {\n type: 'FeatureCollection',\n properties: {\n ...parseSummaryAPI(apiResponse.summary),\n },\n features,\n ...(bbox && { bbox }),\n };\n};\n","import type { ServiceTemplate } from '../shared';\nimport { post } from '../shared/fetch';\nimport { geometrySearchRequestSchema } from './geometrySearchRequestSchema';\nimport { buildGeometrySearchRequest } from './requestBuilder';\nimport { parseGeometrySearchResponse } from './responseParser';\nimport type {\n GeometrySearchParams,\n GeometrySearchRequestAPI,\n GeometrySearchResponse,\n GeometrySearchResponseAPI,\n} from './types';\n\n/**\n * Geometry search service template type.\n */\nexport type GeometrySearchTemplate = ServiceTemplate<\n GeometrySearchParams,\n GeometrySearchRequestAPI,\n GeometrySearchResponseAPI,\n GeometrySearchResponse\n>;\n\n/**\n * Geometry search service template main implementation.\n */\nexport const geometrySearchTemplate: GeometrySearchTemplate = {\n requestValidation: { schema: geometrySearchRequestSchema },\n buildRequest: buildGeometrySearchRequest,\n sendRequest: post,\n parseResponse: parseGeometrySearchResponse,\n};\n","import { callService } from '../shared/serviceTemplate';\nimport type { GeometrySearchTemplate } from './geometrySearchTemplate';\nimport { geometrySearchTemplate } from './geometrySearchTemplate';\nimport type { GeometrySearchParams, GeometrySearchResponse } from './types';\n\n/**\n * Search for places within specific geographic boundaries.\n *\n * The Geometry Search service finds places that fall within one or more defined areas,\n * such as polygons, circles, or corridors. This is essential for location-based filtering\n * and spatial queries where you need results constrained to specific regions.\n *\n * @remarks\n * Key features:\n * - **Area-based search**: Find places within polygons, circles, or along routes\n * - **Multiple geometries**: Search across several areas simultaneously\n * - **Precise boundaries**: Only returns results within the specified areas\n * - **Combined with text**: Filter by query text within the geometric boundaries\n * - **Category filtering**: Narrow results by POI categories\n *\n * Common use cases:\n * - **Route-based search**: \"Find gas stations along my route\"\n * - **Area filtering**: \"Restaurants within this neighborhood polygon\"\n * - **Corridor search**: \"Hotels within 5km of the highway\"\n * - **Service areas**: \"Stores within our delivery zone\"\n * - **Geofencing**: Places within administrative or custom boundaries\n *\n * @param params Geometry search parameters including geometries and optional query\n * @param customTemplate Advanced customization for request/response handling\n *\n * @returns Promise resolving to places within the specified geometries\n *\n * @example\n * ```typescript\n * // Search within a polygon (neighborhood boundaries)\n * const inArea = await geometrySearch({\n * key: 'your-api-key',\n * query: 'coffee shop',\n * geometries: [{\n * type: 'Polygon',\n * coordinates: [[\n * [4.88, 52.36],\n * [4.90, 52.36],\n * [4.90, 52.38],\n * [4.88, 52.38],\n * [4.88, 52.36]\n * ]]\n * }]\n * });\n *\n * // Find POIs along a route corridor\n * const alongRoute = await geometrySearch({\n * key: 'your-api-key',\n * query: 'gas station',\n * geometries: [routeLineString], // From calculateRoute result\n * geometryList: [{\n * position: 0,\n * radius: 5000 // 5km corridor along route\n * }]\n * });\n *\n * // Search multiple areas at once\n * const multiArea = await geometrySearch({\n * key: 'your-api-key',\n * query: 'pharmacy',\n * geometries: [polygonA, polygonB, polygonC],\n * limit: 20\n * });\n *\n * // Category search within geometry\n * const restaurants = await geometrySearch({\n * key: 'your-api-key',\n * categorySet: [7315], // Restaurant category\n * geometries: [cityBoundary]\n * });\n * ```\n *\n * @see [Geometry Search API Documentation](https://docs.tomtom.com/search-api/documentation/search-service/geometry-search)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Search Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/search)\n *\n * @ignore (exposed via 'search')\n */\nexport const geometrySearch = async (\n params: GeometrySearchParams,\n customTemplate?: Partial<GeometrySearchTemplate>,\n): Promise<GeometrySearchResponse> =>\n callService(params, { ...geometrySearchTemplate, ...customTemplate }, 'GeometrySearch');\n\nexport default geometrySearch;\n","import { geometrySearch } from './geometrySearch';\nimport type { GeometrySearchTemplate } from './geometrySearchTemplate';\nimport { geometrySearchTemplate } from './geometrySearchTemplate';\nimport { buildGeometrySearchRequest } from './requestBuilder';\nimport { parseGeometrySearchResponse } from './responseParser';\n\nconst customize: {\n geometrySearch: typeof geometrySearch;\n buildGeometrySearchRequest: typeof buildGeometrySearchRequest;\n parseGeometrySearchResponse: typeof parseGeometrySearchResponse;\n geometrySearchTemplate: GeometrySearchTemplate;\n} = {\n geometrySearch,\n buildGeometrySearchRequest,\n parseGeometrySearchResponse,\n geometrySearchTemplate,\n};\nexport default customize;\n","import { views } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\n\nconst placeByIdRequestMandatory = z.object({\n entityId: z.string().describe('Unique identifier of the place/entity to retrieve'),\n});\n\nconst placeByIdRequestOptional = z.object({\n mapcodes: z.array(z.string()).optional().describe('Request mapcode representations for location'),\n view: z.enum(views).optional().describe('Geopolitical view for disputed territories'),\n openingHours: z.string().optional().describe('Request opening hours information for the place'),\n timeZone: z.string().optional().describe('Request timezone information for the place location'),\n relatedPois: z.string().optional().describe('Related POI inclusion mode (off, child, parent, all)'),\n});\n\n/**\n * @ignore\n */\nexport const placeByIdRequestSchema = placeByIdRequestMandatory.extend(placeByIdRequestOptional.shape);\n","import type { CommonServiceParams } from '../shared';\nimport { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport {\n appendByJoiningParamValue,\n appendCommonParams,\n appendOptionalParam,\n} from '../shared/request/requestBuildingUtils';\nimport type { PlaceByIdParams } from './types';\n\nconst buildUrlBasePath = (params: CommonServiceParams): string =>\n params.customServiceBaseURL || `${params.commonBaseURL}${PLACES_URL_PATH}/place.json`;\n\n/**\n * Default method for building place by id request from {@link PlaceByIdParams}\n * @param params The place by id parameters, with global configuration already merged into them.\n */\nexport const buildPlaceByIdRequest = (params: PlaceByIdParams): URL => {\n const url = new URL(`${buildUrlBasePath(params)}`);\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n appendOptionalParam(urlParams, 'entityId', params.entityId);\n appendByJoiningParamValue(urlParams, 'mapcodes', params.mapcodes);\n appendOptionalParam(urlParams, 'view', params.view);\n appendOptionalParam(urlParams, 'openingHours', params.openingHours);\n appendOptionalParam(urlParams, 'timeZone', params.timeZone);\n appendOptionalParam(urlParams, 'relatedPois', params.relatedPois);\n return url;\n};\n","import { parseSearchAPIResult } from '../shared/searchResultParsing';\nimport type { PlaceByIdResponse, PlaceByIdResponseAPI } from './types';\n\n/**\n * Default method for parsing place by id response.\n * @param apiResponse The place by id response.\n */\nexport const parsePlaceByIdResponse = (apiResponse: PlaceByIdResponseAPI): PlaceByIdResponse =>\n apiResponse.results?.length ? parseSearchAPIResult(apiResponse.results[0]) : undefined;\n","import type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { placeByIdRequestSchema } from './placeByIdSchema';\nimport { buildPlaceByIdRequest } from './requestBuilder';\nimport { parsePlaceByIdResponse } from './responseParser';\nimport type { PlaceByIdParams, PlaceByIdResponse, PlaceByIdResponseAPI } from './types';\n\n/**\n * Place By Is template type.\n * @ignore\n */\nexport type PlaceByIdTemplate = ServiceTemplate<PlaceByIdParams, URL, PlaceByIdResponseAPI, PlaceByIdResponse>;\n\n/**\n * Place By Id template main implementation.\n * @ignore\n */\nexport const placeByIdTemplate: PlaceByIdTemplate = {\n requestValidation: { schema: placeByIdRequestSchema },\n buildRequest: buildPlaceByIdRequest,\n sendRequest: get,\n parseResponse: parsePlaceByIdResponse,\n};\n","import type { PlaceByIdTemplate } from './placeByIdTemplate';\nimport { placeByIdTemplate } from './placeByIdTemplate';\nimport { buildPlaceByIdRequest } from './requestBuilder';\nimport { parsePlaceByIdResponse } from './responseParser';\n\nconst customize: {\n buildPlaceByIdRequest: typeof buildPlaceByIdRequest;\n parsePlaceByIdResponse: typeof parsePlaceByIdResponse;\n placeByIdTemplate: PlaceByIdTemplate;\n} = {\n buildPlaceByIdRequest,\n parsePlaceByIdResponse,\n placeByIdTemplate,\n};\nexport default customize;\n","import type { ParseResponseError } from '../shared';\nimport { SDKServiceError } from '../shared';\nimport type { RoutingAPIResponseError } from '../shared/types/apiResponseErrorTypes';\n\n/**\n * @ignore\n * @param apiError\n * @param serviceName\n */\nexport const parseRoutingResponseError: ParseResponseError<RoutingAPIResponseError> = (apiError, serviceName) => {\n const { data, message, status } = apiError;\n const errorMessage = data?.error?.description ?? data?.detailedError?.message ?? message;\n return new SDKServiceError(errorMessage, serviceName, status);\n};\n","import { currentTypes, plugTypes } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { loadTypes } from '../types/vehicleRestrictionParams';\n\n// Common validation schemas\nconst positiveNumber = z.number().positive();\nconst nonNegativeNumber = z.number().min(0);\nconst percentageNumber = z.number().min(0).max(100);\n\n// Common optional schemas\nconst optionalPositiveNumber = positiveNumber.optional();\nconst optionalNonNegativeNumber = nonNegativeNumber.optional();\nconst optionalNormalizedNumber = z.number().min(0).max(1).optional();\n\n// Speed to consumption rate schema\nconst speedToConsumptionRateSchema = z.object({\n speedKMH: z.number().describe('Speed in kilometers per hour'),\n consumptionUnitsPer100KM: z.number().describe('Consumption rate per 100 kilometers'),\n});\n\n// Efficiency schema for consumption models\nconst efficiencySchema = z\n .object({\n acceleration: optionalNormalizedNumber.describe('Acceleration efficiency factor (0-1)'),\n deceleration: optionalNormalizedNumber.describe('Deceleration efficiency factor (0-1)'),\n uphill: optionalNormalizedNumber.describe('Uphill efficiency factor (0-1)'),\n downhill: optionalNormalizedNumber.describe('Downhill efficiency factor (0-1)'),\n })\n .optional();\n\n// Base consumption model schema\nconst baseConsumptionModelSchema = {\n efficiency: efficiencySchema,\n};\n\n// Consumption array validation\nconst speedConsumptionArray = z.array(speedToConsumptionRateSchema).min(1).max(25);\n\n// Combustion consumption model schema\nconst combustionConsumptionModelSchema = z.object({\n ...baseConsumptionModelSchema,\n speedsToConsumptionsLiters: speedConsumptionArray.describe(\n 'Array of speed-to-fuel-consumption mappings in liters per 100km',\n ),\n auxiliaryPowerInLitersPerHour: optionalNonNegativeNumber.describe('Auxiliary power consumption in liters per hour'),\n fuelEnergyDensityInMJoulesPerLiter: z\n .number()\n .min(1)\n .optional()\n .describe('Fuel energy density in megajoules per liter'),\n});\n\n// Electric consumption model schema\nconst electricConsumptionModelSchema = z.object({\n ...baseConsumptionModelSchema,\n speedsToConsumptionsKWH: speedConsumptionArray.describe(\n 'Array of speed-to-energy-consumption mappings in kWh per 100km',\n ),\n auxiliaryPowerInkW: optionalNonNegativeNumber.describe('Auxiliary power consumption in kilowatts'),\n consumptionInKWHPerKMAltitudeGain: z\n .number()\n .max(500)\n .optional()\n .describe('Energy consumption per kilometer of altitude gain in kWh'),\n recuperationInKWHPerKMAltitudeLoss: optionalNonNegativeNumber.describe(\n 'Energy recuperation per kilometer of altitude loss in kWh',\n ),\n});\n\n// Charging connector schema\nconst chargingConnectorSchema = z.object({\n currentType: z.enum(currentTypes).describe('Type of electrical current (AC or DC)'),\n plugTypes: z.array(z.enum(plugTypes)).min(1).describe('Compatible plug/connector types'),\n efficiency: optionalNormalizedNumber.describe('Charging efficiency factor (0-1)'),\n baseLoadInkW: optionalNonNegativeNumber.describe('Base load in kilowatts'),\n maxPowerInkW: optionalNonNegativeNumber.describe('Maximum charging power in kilowatts'),\n maxVoltageInV: optionalNonNegativeNumber.describe('Maximum voltage in volts'),\n maxCurrentInA: optionalNonNegativeNumber.describe('Maximum current in amperes'),\n voltageRange: z\n .object({\n minVoltageInV: optionalNonNegativeNumber.describe('Minimum voltage in volts'),\n maxVoltageInV: z.number().optional().describe('Maximum voltage in volts'),\n })\n .optional()\n .describe('Acceptable voltage range'),\n});\n\n// Battery curve schema\nconst batteryCurveSchema = z.object({\n stateOfChargeInkWh: nonNegativeNumber.describe('State of charge in kilowatt-hours'),\n maxPowerInkW: positiveNumber.describe('Maximum charging power at this state of charge in kilowatts'),\n});\n\n// Charging model schema\nconst chargingModelSchema = z.object({\n maxChargeKWH: positiveNumber.describe('Maximum battery capacity in kilowatt-hours'),\n batteryCurve: z\n .array(batteryCurveSchema)\n .max(20)\n .optional()\n .describe('Battery charging curve with up to 20 data points'),\n chargingConnectors: z\n .array(chargingConnectorSchema)\n .min(1)\n .optional()\n .describe('Available charging connectors on the vehicle'),\n chargingTimeOffsetInSec: optionalNonNegativeNumber.describe('Time offset for charging start in seconds'),\n});\n\n// Engine model schemas\nconst combustionEngineModelSchema = z.object({\n consumption: combustionConsumptionModelSchema.describe('Fuel consumption model for combustion engine'),\n});\nconst electricEngineModelSchema = z.object({\n consumption: electricConsumptionModelSchema.describe('Energy consumption model for electric engine'),\n charging: chargingModelSchema.optional().describe('Battery and charging specifications'),\n});\n\n// Vehicle dimensions schema\nconst vehicleDimensionsSchema = z\n .object({\n lengthMeters: optionalPositiveNumber.describe('Vehicle length in meters'),\n widthMeters: optionalPositiveNumber.describe('Vehicle width in meters'),\n heightMeters: optionalPositiveNumber.describe('Vehicle height in meters'),\n weightKG: optionalPositiveNumber.describe('Vehicle weight in kilograms'),\n axleWeightKG: optionalPositiveNumber.describe('Vehicle axle weight in kilograms'),\n })\n .optional();\n\n// Vehicle model schemas\nconst predefinedVehicleModelSchema = z.object({\n variantId: z.string().describe('Predefined vehicle variant identifier'),\n});\nconst explicitVehicleModelSchema = z.object({\n dimensions: vehicleDimensionsSchema.describe('Physical dimensions and weight of the vehicle'),\n engine: z\n .union([combustionEngineModelSchema, electricEngineModelSchema])\n .optional()\n .describe('Engine type and consumption characteristics'),\n});\nconst vehicleModelSchema = z.union([predefinedVehicleModelSchema, explicitVehicleModelSchema]).optional();\n\n// Vehicle state schemas\nconst genericVehicleStateSchema = z.object({\n heading: z.number().min(0).max(360).optional().describe('Current vehicle heading in degrees (0-360)'),\n});\n\nconst combustionVehicleStateSchema = genericVehicleStateSchema.extend({\n currentFuelInLiters: nonNegativeNumber.describe('Current fuel level in liters'),\n});\n\nconst electricVehicleStateByPercentageSchema = genericVehicleStateSchema.extend({\n currentChargePCT: percentageNumber.describe('Current battery charge as percentage (0-100)'),\n});\n\nconst electricVehicleStateByKwhSchema = genericVehicleStateSchema.extend({\n currentChargeInkWh: nonNegativeNumber.describe('Current battery charge in kilowatt-hours'),\n});\n\nconst electricVehicleStateSchema = z.union([electricVehicleStateByPercentageSchema, electricVehicleStateByKwhSchema]);\n\n// Charging preferences schemas\nconst chargingPreferencesPCTSchema = z.object({\n minChargeAtDestinationPCT: percentageNumber.describe(\n 'Minimum battery charge percentage required at destination (0-100)',\n ),\n minChargeAtChargingStopsPCT: z\n .number()\n .min(0)\n .max(50)\n .describe('Minimum battery charge percentage at charging stops (0-50)'),\n});\n\nconst chargingPreferencesKWHSchema = z.object({\n minChargeAtDestinationInkWh: nonNegativeNumber.describe('Minimum battery charge in kWh required at destination'),\n minChargeAtChargingStopsInkWh: nonNegativeNumber.describe('Minimum battery charge in kWh at charging stops'),\n});\n\nconst chargingPreferencesSchema = z.union([chargingPreferencesPCTSchema, chargingPreferencesKWHSchema]);\nconst electricVehiclePreferencesSchema = z.object({\n chargingPreferences: chargingPreferencesSchema\n .optional()\n .describe('Preferences for charging stops along the route'),\n});\n\n// Vehicle restrictions schema\nconst vehicleRestrictionsSchema = z\n .object({\n loadTypes: z\n .array(z.enum(loadTypes))\n .optional()\n .describe('Types of hazardous or restricted loads being carried'),\n maxSpeedKMH: z\n .number()\n .min(0)\n .max(250)\n .optional()\n .describe('Maximum vehicle speed in kilometers per hour (0-250)'),\n adrCode: z\n .enum(['B', 'C', 'D', 'E'])\n .optional()\n .describe('ADR tunnel restriction code for hazardous materials'),\n commercial: z.boolean().optional().describe('Whether the vehicle is used for commercial purposes'),\n })\n .optional();\n\n// Base vehicle parameters schema\nconst baseVehicleParamsSchema = {\n model: vehicleModelSchema,\n restrictions: vehicleRestrictionsSchema,\n};\n\n// Vehicle parameters schemas\nconst genericVehicleParamsSchema = z.object({\n ...baseVehicleParamsSchema,\n engineType: z.undefined(),\n state: genericVehicleStateSchema.optional().describe('Current state of the vehicle'),\n preferences: z.object({}).optional().describe('Vehicle preferences'),\n});\n\nconst combustionVehicleParamsSchema = z.object({\n ...baseVehicleParamsSchema,\n engineType: z.literal('combustion').describe('Combustion engine type'),\n state: combustionVehicleStateSchema\n .optional()\n .describe('Current state of the combustion vehicle including fuel level'),\n preferences: z.object({}).optional().describe('Combustion vehicle preferences'),\n});\n\nconst electricVehicleParamsSchema = z.object({\n ...baseVehicleParamsSchema,\n engineType: z.literal('electric').describe('Electric engine type'),\n state: electricVehicleStateSchema\n .optional()\n .describe('Current state of the electric vehicle including battery charge'),\n preferences: electricVehiclePreferencesSchema\n .optional()\n .describe('Electric vehicle preferences including charging requirements'),\n});\n\n/**\n * @ignore\n */\nexport const vehicleParametersSchema = z.union([\n z.discriminatedUnion('engineType', [combustionVehicleParamsSchema, electricVehicleParamsSchema]),\n genericVehicleParamsSchema,\n]);\n","/**\n * Known hazardous truck load types. Should be used for trucks carrying hazardous materials.\n */\nexport const loadTypes = [\n 'USHazmatClass1',\n 'USHazmatClass2',\n 'USHazmatClass3',\n 'USHazmatClass4',\n 'USHazmatClass5',\n 'USHazmatClass6',\n 'USHazmatClass7',\n 'USHazmatClass8',\n 'USHazmatClass9',\n 'otherHazmatExplosive',\n 'otherHazmatGeneral',\n 'otherHazmatHarmfulToWater',\n] as const;\n\n/**\n * Known hazardous truck load types. Should be used for trucks carrying hazardous materials.\n *\n * Use these values for routing in the USA:\n * * USHazmatClass1: Explosives\n * * USHazmatClass2: Compressed gas\n * * USHazmatClass3: Flammable liquids\n * * USHazmatClass4: Flammable solids\n * * USHazmatClass5: Oxidizers\n * * USHazmatClass6: Poisons\n * * USHazmatClass7: Radioactive\n * * USHazmatClass8: Corrosives\n * * USHazmatClass9: Miscellaneous\n *\n * Use these values for routing in all other countries:\n * * otherHazmatExplosive: Explosives\n * * otherHazmatGeneral: Miscellaneous\n * * otherHazmatHarmfulToWater: Harmful to water\n */\nexport type LoadType = (typeof loadTypes)[number];\n\n/**\n * Parameters for a vehicle which are related to restrictions (e.g. related to the cargo and purpose of the vehicle).\n */\nexport type VehicleRestrictions = {\n /**\n * Vehicle restrictions including load types, speed limits, ADR codes, and commercial usage.\n */\n restrictions?: {\n /**\n * Specifies types of cargo that may be classified as hazardous materials and are restricted from some roads.\n */\n loadTypes?: LoadType[];\n /**\n * Maximum speed of the vehicle in kilometers/hour.\n * * Must have a value in the range [0, 250].\n * * A value of 0 means that an appropriate value for the vehicle will be determined and applied during route planning.\n *\n * @default 0\n */\n maxSpeedKMH?: number;\n /**\n * Subjects the vehicle to ADR tunnel restrictions.\n * * Vehicles with code B are restricted from roads with ADR tunnel categories B, C, D, and E.\n * * Vehicles with code C are restricted from roads with ADR tunnel categories C, D, and E.\n * * Vehicles with code D are restricted from roads with ADR tunnel categories D and E.\n * * Vehicles with code E are restricted from roads with ADR tunnel category E.\n *\n * Notes:\n * If travelMode is pedestrian or bicycle, adrCode is not considered.\n * The adrCode and loadType parameters are independent; please provide both if applicable.\n * @see https://unece.org/about-adr\n */\n adrCode?: 'B' | 'C' | 'D' | 'E';\n /**\n *\n * The vehicle is used for commercial purposes (big letters on the side) and thus may not be allowed to drive on some roads.\n * This restriction is applicable only in some countries (e.g. US).\n *\n * @default false\n */\n commercial?: boolean;\n };\n};\n","import { avoidableTypes } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { routeTypes } from '../types/commonRoutingParams';\nimport { vehicleParametersSchema } from './vehicleParamsSchema';\n\n/**\n * @ignore\n */\nexport const commonRoutingRequestSchema = z.object({\n costModel: z\n .object({\n avoid: z\n .array(z.enum(avoidableTypes))\n .optional()\n .describe('Road types and features to avoid when calculating route'),\n traffic: z\n .enum(['live', 'historical'])\n .optional()\n .describe(\n 'Traffic consideration mode (live: real-time + historical, historical: typical patterns only)',\n ),\n routeType: z\n .enum(routeTypes)\n .optional()\n .describe('Route optimization strategy (fast, short, efficient, thrilling)'),\n thrillingParams: z\n .object({\n hilliness: z\n .enum(['low', 'normal', 'high'])\n .optional()\n .describe('Level of hilliness for thrilling routes'),\n windingness: z\n .enum(['low', 'normal', 'high'])\n .optional()\n .describe('Level of windingness for thrilling routes'),\n })\n .optional()\n .describe('Optional parameters for thrilling route type'),\n })\n .optional()\n .describe('Cost model criteria for route optimization'),\n travelMode: z.string().optional().describe('Travel mode (car, truck, pedestrian, bicycle)'),\n vehicle: vehicleParametersSchema\n .optional()\n .describe('Vehicle-specific parameters including dimensions, engine type, and consumption model'),\n when: z\n .object({\n option: z.enum(['departAt', 'arriveBy']).describe('Whether to specify a departure or arrival time'),\n date: z.date().describe('The date and time to depart or arrive'),\n })\n .optional()\n .describe('Departure or arrival time specification for route planning'),\n});\n","import type { Avoidable, TravelMode } from '@tomtom-org/maps-sdk/core';\nimport { VehicleParameters } from './vehicleParams';\n\n/**\n * Basic low/normal/high intensity level option.\n *\n * Used for configuring route characteristics like hilliness or windingness.\n *\n * @remarks\n * - `low`: Minimal intensity\n * - `normal`: Moderate intensity\n * - `high`: Maximum intensity\n *\n * @group Routing\n */\nexport type LNH = 'low' | 'normal' | 'high';\n\n// TODO: there is no slope data yet in Orbis, thus hilliness isn't supported yet\n// /**\n// * Options applicable to the thrilling route type.\n// */\n// export type ThrillingParams = {\n// /**\n// * The level of hilliness on a thrilling route.\n// * * Possible values: low, normal, high.\n// * * This parameter can only be used in conjunction with routeType thrilling.\n// * @default None\n// */\n// hilliness?: LNH;\n//\n// /**\n// * The level of windingness on a thrilling route.\n// *\n// * * Possible values: low, normal, high.\n// * * This parameter can only be used in conjunction with routeType thrilling.\n// * @default None\n// */\n// windingness?: LNH;\n// };\n\n/**\n * Available route types, where each type specifies the type of optimization used when calculating routes:\n * * **fast**: Route calculation is optimized by travel time, while keeping the routes sensible. For example, the calculation may avoid shortcuts along inconvenient side roads or long detours that only save very little time.\n * * **short**: Route calculation is optimized such that a good compromise between small travel time and short travel distance is achieved.\n * * **efficient**: Route calculation is optimized such that a good compromise between small travel time and low fuel or energy consumption is achieved.\n * * **thrilling**: Route calculation is optimized such that routes include interesting or challenging roads and use as few motorways as possible.\n * There is a limit of 900km on routes planned with routeType=thrilling.\n *\n * @group Routing\n */\nexport const routeTypes = ['fast', 'short', 'efficient', 'thrilling'] as const;\n\n/**\n * Route optimization strategy for route calculation.\n *\n * Determines what the routing engine optimizes for when calculating the route.\n * Each type produces different routes suited to different use cases.\n *\n * @remarks\n * **Route Type Strategies:**\n *\n * - **`fast`**: Minimize travel time while maintaining practicality\n * - Prefers major roads and highways\n * - Avoids unnecessary detours and shortcuts on minor roads\n * - Best for most everyday use cases (commuting, business travel)\n *\n * - **`short`**: Balance between time and distance\n * - Good compromise between speed and mileage\n * - May use smaller roads to save distance\n * - Useful for short trips or when fuel costs matter\n *\n * - **`efficient`**: Minimize fuel or energy consumption\n * - Optimizes for least energy use\n * - Considers vehicle consumption model\n * - Avoids rapid acceleration/deceleration\n * - Best used with vehicle consumption parameters\n *\n * - **`thrilling`**: Scenic and engaging routes\n * - Prefers curvy, interesting roads\n * - Minimizes motorway usage\n * - **Limited to 900km maximum route length**\n * - Ideal for motorcycle rides or scenic drives\n *\n * @example\n * ```typescript\n * // Fastest route for commuting\n * const routeType: RouteType = 'fast';\n *\n * // Most fuel-efficient route for long trip\n * const ecoRoute: RouteType = 'efficient';\n *\n * // Scenic route for leisure\n * const scenicRoute: RouteType = 'thrilling';\n * ```\n *\n * @group Routing\n */\nexport type RouteType = (typeof routeTypes)[number];\n\n/**\n * Traffic consideration mode for route calculation.\n *\n * Controls how traffic conditions are factored into routing and travel time estimates.\n *\n * @remarks\n * **Traffic Modes:**\n *\n * - **`live`**: Real-time + historical traffic\n * - Includes current traffic jams and incidents\n * - Considers short-term and long-term road closures\n * - Most accurate for immediate departures\n * - Updates with current conditions\n *\n * - **`historical`**: Typical traffic patterns only\n * - Based on historical data for time of day/week\n * - Ignores current traffic conditions\n * - Good for future trip planning\n * - More predictable for scheduled departures\n *\n * @example\n * ```typescript\n * // Route considering current traffic (departing now)\n * const trafficMode: TrafficInput = 'live';\n *\n * // Route based on typical patterns (planning ahead)\n * const plannedRoute: TrafficInput = 'historical';\n * ```\n *\n * @group Routing\n */\nexport type TrafficInput = 'live' | 'historical';\n\n/**\n * Cost model criteria for route optimization.\n *\n * Defines routing preferences and constraints that influence path selection.\n * Combines route type, traffic consideration, and avoidance criteria to determine\n * what makes a route \"better\" in the eyes of the routing engine.\n *\n * @remarks\n * The cost model affects how the route path is calculated, but does not affect what other data the response includes.\n *\n * The cost model balances multiple factors:\n * - Time efficiency\n * - Distance\n * - Fuel/energy consumption\n * - User preferences (avoid tolls, ferries, etc.)\n * - Traffic conditions\n *\n * @example\n * ```typescript\n * // Fast route avoiding tolls\n * const costModel: CostModel = {\n * routeType: 'fast',\n * traffic: 'live',\n * avoid: ['tollRoads']\n * };\n *\n * // Eco-friendly route avoiding highways\n * const ecoCostModel: CostModel = {\n * routeType: 'efficient',\n * traffic: 'historical',\n * avoid: ['motorways', 'ferries']\n * };\n *\n * // Scenic route for leisure\n * const scenicCostModel: CostModel = {\n * routeType: 'thrilling',\n * avoid: ['motorways', 'tollRoads']\n * };\n * ```\n *\n * @group Routing\n */\nexport type CostModel = {\n /**\n * Specifies something that the route calculation should try to avoid when determining the route.\n * @default None\n */\n avoid?: Avoidable[];\n\n /**\n * Decides how traffic is considered for computing routes.\n *\n * Possible values are:\n * * live: In addition to historical travel times, routing and estimated travel time\n * consider traffic jams and short- and long-term closures during the travel time window.\n * * historical: Routing and estimated travel time consider historical travel times and long term closures.\n * Traffic jams and short-term closures during the travel time window do not influence routing or travel time.\n *\n * @default live\n *\n * @remarks\n * This setting does not affect whether live traffic is included in the response or not.\n * * Considering historical traffic in cost model does not mean live traffic is not included in the response.\n */\n traffic?: TrafficInput;\n\n /**\n * Specifies the type of optimization used when calculating routes.\n * Possible values are:\n *\n * * **fast**: Route calculation is optimized by travel time, while keeping the routes sensible. For example, the calculation may avoid shortcuts along inconvenient side roads or long detours that only save very little time.\n * * **short**: Route calculation is optimized such that a good compromise between small travel time and short travel distance is achieved.\n * * **efficient**: Route calculation is optimized such that a good compromise between small travel time and low fuel or energy consumption is achieved.\n * * **thrilling**: Route calculation is optimized such that routes include interesting or challenging roads and use as few motorways as possible.\n * There is a limit of 900km on routes planned with routeType=thrilling.\n * @default fast\n */\n routeType?: RouteType;\n\n /**\n * Optional parameters if the route type is \"thrilling\" to indicate how curvy and hilly the route should be.\n */\n // TODO not supported yet in Orbis (no slope data)\n // thrillingParams?: ThrillingParams;\n};\n\ntype DepartArriveOption = 'departAt' | 'arriveBy';\n\n/**\n * Departure or arrival time specification for route planning.\n *\n * Allows specifying either when to depart from the origin or when to arrive at the destination.\n * The routing engine calculates the route optimized for that specific time window, considering\n * traffic patterns for that time of day.\n *\n * @typeParam Option - Whether this specifies departure or arrival time\n *\n * @remarks\n * Traffic conditions vary significantly by:\n * - Time of day (rush hour vs off-peak)\n * - Day of week (weekday vs weekend)\n * - Special events or holidays\n *\n * Specifying a departure or arrival time enables the router to:\n * - Use appropriate traffic data for that time\n * - Plan around rush hour or quiet periods\n * - Calculate accurate arrival/departure times\n * - Account for time-dependent road restrictions\n *\n * **Important Notes:**\n * - Times are processed in the timezone of the origin/destination\n *\n * @example\n * ```typescript\n * // Depart at specific time (morning commute)\n * const departParams: DepartArriveParams = {\n * option: 'departAt',\n * date: new Date('2025-10-20T08:00:00Z')\n * };\n *\n * // Arrive by specific time (catch a flight)\n * const arriveParams: DepartArriveParams = {\n * option: 'arriveBy',\n * date: new Date('2025-10-20T14:00:00Z')\n * };\n *\n * // Plan route avoiding rush hour\n * const offPeakDepart: DepartArriveParams = {\n * option: 'departAt',\n * date: new Date('2025-10-20T10:30:00Z') // After morning rush\n * };\n * ```\n *\n * @group Routing\n */\nexport type DepartArriveParams<Option extends DepartArriveOption = DepartArriveOption> = {\n /**\n * Whether to specify a departure or arrival time.\n *\n * @remarks\n * - `departAt`: Calculate route from this departure time forward\n * - `arriveBy`: Calculate route backward to arrive by this time\n */\n option: Option;\n\n /**\n * The date and time to depart or arrive.\n *\n * @remarks\n * If past dates are supplied or dates that are impossible to achieve\n * (e.g., an imminent arrival date for a very long route), the system\n * will default to departing immediately.\n *\n * Times should be specified in ISO 8601 format or as JavaScript Date objects.\n */\n date: Date;\n};\n\n/**\n * Common parameters shared across all routing service requests.\n *\n * These parameters configure how routes are calculated, including optimization\n * strategy, vehicle characteristics, timing constraints, and travel preferences.\n * They provide a consistent interface across different routing services.\n *\n * @remarks\n * Most routing services (calculateRoute, calculateMatrixRoute, calculateReachableRange)\n * accept these parameters to customize route calculation. They control:\n * - What to optimize for (time, distance, fuel)\n * - Vehicle constraints and capabilities\n * - When to travel (affecting traffic)\n * - What features to avoid\n * - Mode of transportation\n *\n * **Service Compatibility:**\n * - {@link calculateRoute}: All parameters supported\n * - {@link calculateMatrixRoute}: Subset of parameters\n * - {@link calculateReachableRange}: Subset of parameters\n *\n * @example\n * ```typescript\n * // Standard car route avoiding tolls\n * const routingParams: CommonRoutingParams = {\n * costModel: {\n * routeType: 'fast',\n * traffic: 'live',\n * avoid: ['tollRoads']\n * },\n * travelMode: 'car',\n * when: {\n * option: 'departAt',\n * date: new Date('2025-10-20T08:00:00Z')\n * }\n * };\n *\n * // Electric vehicle route with consumption model\n * const evRoutingParams: CommonRoutingParams = {\n * costModel: {\n * routeType: 'efficient',\n * traffic: 'live'\n * },\n * travelMode: 'car',\n * vehicle: {\n * engineType: 'electric',\n * model: {\n * dimensions: {\n * weightKG: 2000\n * },\n * engine: {\n * consumption: {\n * speedToConsumption: [\n * { speedKMH: 50, consumptionUnitsPer100KM: 15 },\n * { speedKMH: 90, consumptionUnitsPer100KM: 18 },\n * { speedKMH: 120, consumptionUnitsPer100KM: 22 }\n * ]\n * }\n * }\n * },\n * state: {\n * currentChargeInkWh: 60\n * }\n * }\n * };\n *\n * // Truck route with restrictions\n * const truckParams: CommonRoutingParams = {\n * costModel: {\n * routeType: 'short',\n * avoid: ['tollRoads', 'ferries']\n * },\n * travelMode: 'truck',\n * vehicle: {\n * model: {\n * dimensions: {\n * lengthMeters: 16.5,\n * widthMeters: 2.5,\n * heightMeters: 4.0,\n * weightKG: 40000\n * },\n * restrictions: {\n * restrictions: {\n * commercial: true,\n * maxSpeedKMH: 90\n * }\n * }\n * }\n * }\n * };\n * ```\n *\n * @see [Common Routing Parameters Documentation](https://docs.tomtom.com/routing-api/documentation/routing/common-routing-parameters)\n *\n * @group Routing\n */\nexport type CommonRoutingParams = {\n /**\n * Criteria that specifies what paths to prefer during routing.\n */\n costModel?: CostModel;\n\n /**\n * The primary means of transportation to be used while routing.\n *\n * The travel mode for the requested route.\n * Note that the requested travelMode may not be available for the entire route. Where\n * the requested travelMode is not available for a particular section, the element of the\n * response for that section will be 'other'.\n * @default None\n */\n travelMode?: TravelMode;\n\n /**\n * Specifies when to depart or arrive.\n * If past dates are supplied or in a way that are impossible to achieve\n * (e.g. an imminent arrival date for a long route), then it will default to departing now.\n * @default depart now\n */\n when?: DepartArriveParams;\n\n /**\n * Parameters for the vehicle that will be used to drive the route.\n */\n vehicle?: VehicleParameters;\n\n /**\n * The version of the API to use.\n * * The SDK will use the right default when not specified.\n * * Use it only if you really need to target a specific API version.\n */\n apiVersion?: number;\n};\n","import type { HasLngLat } from '@tomtom-org/maps-sdk/core';\nimport type { CommonRoutingParams, CommonServiceParams, DepartArriveParams } from '../../shared';\nimport type { ReachableRangeRequestAPI } from './apiRequestTypes';\nimport type { ReachableRangeResponseAPI } from './apiResponseTypes';\n\nexport const budgetTypes = [\n 'timeMinutes',\n 'remainingChargeCPT',\n 'spentChargePCT',\n 'spentFuelLiters',\n 'distanceKM',\n] as const;\n\n/**\n * Type of budget constraint for reachable range calculation.\n *\n * @remarks\n * **Budget Types:**\n * - `timeMinutes`: Travel time in minutes (isochrone)\n * - `distanceKM`: Travel distance in kilometers (isodistance)\n * - `remainingChargeCPT`: Remaining battery charge in percentage (EV)\n * - `spentChargePCT`: Battery charge consumed in percentage (EV)\n * - `spentFuelLiters`: Fuel consumed in liters (combustion)\n *\n * **Common Use Cases:**\n * - Time: \"Where can I reach in 30 minutes?\"\n * - Distance: \"What's within 10 km?\"\n * - EV charge: \"How far can I go on 50% battery?\"\n * - Fuel: \"Range with 20 liters of fuel\"\n *\n * @example\n * ```typescript\n * const timeType: BudgetType = 'timeMinutes';\n * const distanceType: BudgetType = 'distanceKM';\n * const evType: BudgetType = 'remainingChargeCPT';\n * ```\n *\n * @group Reachable Range\n */\nexport type BudgetType = (typeof budgetTypes)[number];\n\n/**\n * Budget constraint for reachable range calculation.\n *\n * Defines the limit (time, distance, or fuel/charge) for calculating\n * how far you can travel from a starting point.\n *\n * @remarks\n * **Use Cases:**\n * - Service area visualization (30-min delivery zone)\n * - EV range anxiety mitigation (show reachable area)\n * - Emergency response coverage (10-min response time)\n * - Delivery zone planning\n * - Store location analysis\n *\n * @example\n * ```typescript\n * // 30-minute travel time\n * const timeBudget: ReachableRangeBudget = {\n * type: 'timeMinutes',\n * value: 30\n * };\n *\n * // 50 km distance\n * const distanceBudget: ReachableRangeBudget = {\n * type: 'distanceKM',\n * value: 50\n * };\n *\n * // 50% battery remaining\n * const evBudget: ReachableRangeBudget = {\n * type: 'remainingChargeCPT',\n * value: 50\n * };\n *\n * // 20 liters of fuel\n * const fuelBudget: ReachableRangeBudget = {\n * type: 'spentFuelLiters',\n * value: 20\n * };\n * ```\n *\n * @group Reachable Range\n */\nexport type ReachableRangeBudget = {\n /**\n * The type of budget, including units.\n *\n * @remarks\n * - `timeMinutes`: Minutes of travel time\n * - `distanceKM`: Kilometers of travel distance\n * - `remainingChargeCPT`: Battery percentage remaining\n * - `spentChargePCT`: Battery percentage consumed\n * - `spentFuelLiters`: Liters of fuel consumed\n */\n type: BudgetType;\n\n /**\n * The value of the budget based on the units mentioned in the type.\n *\n * @remarks\n * **Typical Values:**\n * - Time: 5-60 minutes\n * - Distance: 5-100 km\n * - Charge: 10-100 percentage\n * - Fuel: 5-50 liters\n *\n * @example\n * ```typescript\n * value: 30 // 30 minutes/km/percent/liters depending on type\n * value: 15.5 // Decimal values supported\n * ```\n */\n value: number;\n};\n\n/**\n * Parameters specific to reachable range calculation.\n *\n * @remarks\n * These parameters are combined with common routing parameters to calculate\n * the reachable area from a starting point.\n *\n * @group Reachable Range\n */\nexport type ReachableRangeOwnParams = {\n /**\n * Location from which the range calculation should start.\n *\n * @remarks\n * The center point from which reachability is calculated. Can be:\n * - An object with `lon` and `lat` properties\n * - An array `[longitude, latitude]`\n *\n * @example\n * ```typescript\n * // Object format\n * origin: { lon: 4.9, lat: 52.3 }\n *\n * // Array format\n * origin: [4.9, 52.3]\n * ```\n */\n origin: HasLngLat;\n\n /**\n * The budget for the reachable range calculation.\n *\n * @remarks\n * Consists of a type indicating whether it's about time, distance, or\n * fuel/charge and the units, plus its value.\n *\n * Determines the extent of the reachable area polygon.\n */\n budget: ReachableRangeBudget;\n\n /**\n * Maximum ferry length in meters to consider.\n *\n * @remarks\n * Ferries longer than this value will be avoided in the calculation.\n * Useful for excluding long ferry routes that might extend the range\n * unrealistically.\n *\n * @example\n * ```typescript\n * maxFerryLengthMeters: 5000 // Avoid ferries longer than 5 km\n * ```\n */\n maxFerryLengthMeters?: number;\n\n /**\n * Applies post-processing to smooth the polygon boundary for better visual appearance.\n *\n * @remarks\n * Stronger smoothing generally results in more points.\n *\n * @example\n * ```typescript\n * smoothing: 'strong'\n * ```\n */\n smoothing?: 'none' | 'weak' | 'strong';\n\n /**\n * Specifies when to depart.\n *\n * @remarks\n * If past dates are supplied or dates that are impossible to achieve,\n * it will default to departing now.\n *\n * **Traffic Impact:**\n * - Future departure times use predictive traffic\n * - Current time uses live traffic\n * - Historic times use historical patterns\n *\n * @default Depart now\n *\n * @example\n * ```typescript\n * when: { departAt: new Date('2025-10-20T08:00:00Z') }\n * when: { departAt: 'now' }\n * ```\n */\n when?: DepartArriveParams<'departAt'>;\n};\n\n/**\n * Complete parameters for calculating a reachable range.\n *\n * Combines common service parameters, routing parameters, and reachable range\n * specific options to compute an isochrone or isodistance polygon.\n *\n * @remarks\n * **What it Returns:**\n * A polygon representing the area reachable from the origin within the\n * specified budget (time, distance, or fuel/charge).\n *\n * **Use Cases:**\n * - Delivery zone visualization\n * - Service area mapping\n * - Emergency response coverage\n * - EV range display\n * - Store catchment areas\n * - Real estate search (30-min commute)\n *\n * **Traffic Consideration:**\n * Results vary based on departure time and traffic conditions. Use\n * appropriate `when` values for accurate predictions.\n *\n * @example\n * ```typescript\n * // 30-minute driving range\n * const params: ReachableRangeParams = {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * budget: {\n * type: 'timeMinutes',\n * value: 30\n * },\n * routeType: 'fastest',\n * traffic: 'live',\n * when: { departAt: 'now' }\n * };\n *\n * // 50 km distance range\n * const distanceParams: ReachableRangeParams = {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * budget: {\n * type: 'distanceKM',\n * value: 50\n * }\n * };\n *\n * // EV range with 50% battery\n * const evParams: ReachableRangeParams = {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * budget: {\n * type: 'remainingChargeCPT',\n * value: 50\n * },\n * vehicle: {\n * engineType: 'electric',\n * model: {\n * engine: {\n * consumption: {\n * charging: { maxChargeKWH: 100 }\n * }\n * }\n * },\n * state: {\n * currentChargePCT: 80\n * }\n * }\n * };\n *\n * // Avoid toll roads\n * const noTollParams: ReachableRangeParams = {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * budget: {\n * type: 'timeMinutes',\n * value: 45\n * },\n * avoid: ['tollRoads']\n * };\n * ```\n *\n * @group Reachable Range\n */\nexport type ReachableRangeParams = CommonServiceParams<ReachableRangeRequestAPI, ReachableRangeResponseAPI> &\n CommonRoutingParams &\n ReachableRangeOwnParams;\n","import { z } from 'zod';\nimport { commonRoutingRequestSchema } from '../shared/schema/commonRoutingRequestSchema';\nimport { hasLngLatSchema } from '../shared/schema/geometriesSchema';\nimport { budgetTypes } from './types/reachableRangeParams';\n\n// import { SchemaRefinement } from \"../shared/types/validation\";\n\nconst reachableRangeRequestSchemaMandatory = z.object({\n origin: hasLngLatSchema.describe('Starting position [longitude, latitude] for reachable range calculation'),\n budget: z\n .object({\n type: z.enum(budgetTypes).describe('Budget type (time, distance, or energy/fuel)'),\n value: z.number().min(0).describe('Budget value (depends on type: seconds, meters, liters, or kWh)'),\n })\n .describe('Travel budget constraints for reachable range'),\n});\n\nconst reachableRangeRequestSchemaOptional = z.object({\n maxFerryLengthMeters: z.number().min(0).optional().describe('Maximum ferry distance in meters to include in range'),\n smoothing: z\n .enum(['none', 'weak', 'strong'])\n .optional()\n .describe('Post-processing smoothing level for the polygon boundary'),\n});\n\nconst reachableRangeRequestSchema = commonRoutingRequestSchema.extend(\n reachableRangeRequestSchemaMandatory.extend(reachableRangeRequestSchemaOptional.shape).shape,\n);\n\n// const departArriveRefinement: SchemaRefinement<ReachableRangeParams> = {\n// check: (data: ReachableRangeParams): boolean => (data.when?.option as string) != \"arriveBy\",\n// message: \"When calculating a reachable range, departure date-time can be specified, but not arrival date-time\"\n// };\n\n// const evRangeRefinement: SchemaRefinement<ReachableRangeParams> = {\n// check: (data: ReachableRangeParams): boolean =>\n// !(\n// (data.budget.type === \"remainingChargeCPT\" || data.budget.type === \"spentChargePCT\") &&\n// data.vehicle?.engine?.type != \"electric\"\n// ),\n// message: \"With an EV reachable range, the vehicle parameters must be set, with 'electric' engine type\"\n// };\n//\n// const fuelRangeRefinement: SchemaRefinement<ReachableRangeParams> = {\n// check: (data: ReachableRangeParams): boolean =>\n// !(data.budget.type === \"spentFuelLiters\" && data.vehicle?.engine?.type != \"combustion\"),\n// message: \"With a fuel reachable range, the vehicle parameters must be set, with 'combustion' engine type\"\n// };\n\n/**\n * @ignore\n */\nexport const reachableRangeRequestValidationConfig = {\n schema: reachableRangeRequestSchema,\n // refinements: [evRangeRefinement, fuelRangeRefinement, departArriveRefinement]\n};\n","import { isNil } from 'lodash-es';\nimport {\n CombustionEngineModel,\n ConsumptionModelEfficiency,\n ElectricConsumptionModel,\n ElectricEngineModel,\n SpeedToConsumptionRate,\n VehicleEngineModel,\n VehicleEngineType,\n} from '../types/vehicleEngineParams';\nimport { VehicleDimensions } from '../types/vehicleModel';\nimport { ElectricVehicleParams, VehicleParameters } from '../types/vehicleParams';\nimport { ChargingPreferencesKWH, ChargingPreferencesPCT } from '../types/vehiclePreferences';\nimport { ElectricVehicleStateKWH, ElectricVehicleStatePCT, VehicleState } from '../types/vehicleState';\nimport { appendByRepeatingParamName } from './requestBuildingUtils';\n\nconst appendConsumptionEfficiency = (urlParams: URLSearchParams, efficiency?: ConsumptionModelEfficiency): void => {\n if (efficiency) {\n !isNil(efficiency.acceleration) && urlParams.append('accelerationEfficiency', String(efficiency.acceleration));\n !isNil(efficiency.deceleration) && urlParams.append('decelerationEfficiency', String(efficiency.deceleration));\n !isNil(efficiency.uphill) && urlParams.append('uphillEfficiency', String(efficiency.uphill));\n !isNil(efficiency.downhill) && urlParams.append('downhillEfficiency', String(efficiency.downhill));\n }\n};\n\n// e.g. 50,6.3:130,11.5\nconst buildSpeedToConsumptionString = (speedsToConsumptions: SpeedToConsumptionRate[]): string =>\n speedsToConsumptions\n .map((speedToConsumption) => `${speedToConsumption.speedKMH},${speedToConsumption.consumptionUnitsPer100KM}`)\n .join(':');\n\nconst appendCombustionEngine = (urlParams: URLSearchParams, engine: CombustionEngineModel): void => {\n // (no need to append combustion vehicleEngineType since it's the default)\n const consumptionModel = engine.consumption;\n consumptionModel.speedsToConsumptionsLiters &&\n urlParams.append(\n 'constantSpeedConsumptionInLitersPerHundredkm',\n buildSpeedToConsumptionString(consumptionModel.speedsToConsumptionsLiters),\n );\n !isNil(consumptionModel.auxiliaryPowerInLitersPerHour) &&\n urlParams.append('auxiliaryPowerInLitersPerHour', String(consumptionModel.auxiliaryPowerInLitersPerHour));\n !isNil(consumptionModel.fuelEnergyDensityInMJoulesPerLiter) &&\n urlParams.append(\n 'fuelEnergyDensityInMJoulesPerLiter',\n String(consumptionModel.fuelEnergyDensityInMJoulesPerLiter),\n );\n};\n\nconst appendElectricConsumptionModel = (urlParams: URLSearchParams, model: ElectricConsumptionModel): void => {\n model.speedsToConsumptionsKWH &&\n urlParams.append(\n 'constantSpeedConsumptionInkWhPerHundredkm',\n buildSpeedToConsumptionString(model.speedsToConsumptionsKWH),\n );\n !isNil(model.auxiliaryPowerInkW) && urlParams.append('auxiliaryPowerInkW', String(model.auxiliaryPowerInkW));\n !isNil(model.consumptionInKWHPerKMAltitudeGain) &&\n urlParams.append('consumptionInkWhPerkmAltitudeGain', String(model.consumptionInKWHPerKMAltitudeGain));\n !isNil(model.recuperationInKWHPerKMAltitudeLoss) &&\n urlParams.append('recuperationInkWhPerkmAltitudeLoss', String(model.recuperationInKWHPerKMAltitudeLoss));\n};\n\nconst appendChargingModel = (urlParams: URLSearchParams, engine: ElectricEngineModel): void => {\n const chargingModel = engine.charging;\n if (chargingModel?.maxChargeKWH) {\n urlParams.append('maxChargeInkWh', String(chargingModel.maxChargeKWH));\n }\n // (the rest of the charging model goes as POST data)\n};\n\nconst appendVehicleState = (urlParams: URLSearchParams, vehicleParams: VehicleParameters): void => {\n if (!vehicleParams.state) {\n return;\n }\n\n // Generic state props:\n vehicleParams.state.heading && urlParams.append('vehicleHeading', String(vehicleParams.state.heading));\n\n if (!('engineType' in vehicleParams)) {\n // Generic vehicle, no engine-specific state to append:\n return;\n }\n\n // Engine-specific state props:\n if (vehicleParams.engineType === 'combustion') {\n const combustionState: VehicleState<'combustion'> = vehicleParams.state;\n combustionState.currentFuelInLiters &&\n urlParams.append('currentFuelInLiters', String(combustionState.currentFuelInLiters));\n } else if (vehicleParams.engineType === 'electric') {\n const electricState: VehicleState<'electric'> = vehicleParams.state;\n const kwhElectricState = electricState as ElectricVehicleStateKWH;\n const pctElectricState = electricState as ElectricVehicleStatePCT;\n\n if (kwhElectricState.currentChargeInkWh) {\n urlParams.append('currentChargeInkWh', String(kwhElectricState.currentChargeInkWh));\n } else if (\n pctElectricState.currentChargePCT &&\n vehicleParams.model &&\n 'engine' in vehicleParams.model &&\n vehicleParams.model.engine\n ) {\n const engine = vehicleParams.model.engine;\n const maxChargeKWH = engine.charging?.maxChargeKWH;\n if (maxChargeKWH) {\n // currentChargePCT needs maxChargeKWH to be converted to kWh\n urlParams.append(\n 'currentChargeInkWh',\n String((maxChargeKWH * pctElectricState.currentChargePCT) / 100),\n );\n }\n }\n }\n};\n\nconst appendVehiclePreferences = (urlParams: URLSearchParams, vehicleParams: VehicleParameters): void => {\n if (!vehicleParams.preferences) {\n return;\n }\n\n if ('engineType' in vehicleParams && vehicleParams.engineType === 'electric') {\n const preferences = vehicleParams.preferences;\n if (preferences.chargingPreferences) {\n const chargingPrefs = preferences.chargingPreferences;\n const kwhChargingPrefs = chargingPrefs as ChargingPreferencesKWH;\n const pctChargingPrefs = chargingPrefs as ChargingPreferencesPCT;\n\n // Check if absolute kWh values are available and use them directly\n if (kwhChargingPrefs.minChargeAtChargingStopsInkWh || kwhChargingPrefs.minChargeAtDestinationInkWh) {\n urlParams.append('minChargeAtDestinationInkWh', String(kwhChargingPrefs.minChargeAtDestinationInkWh));\n urlParams.append(\n 'minChargeAtChargingStopsInkWh',\n String(kwhChargingPrefs.minChargeAtChargingStopsInkWh),\n );\n } else if (\n (pctChargingPrefs.minChargeAtChargingStopsPCT || pctChargingPrefs.minChargeAtDestinationPCT) &&\n vehicleParams.model &&\n 'engine' in vehicleParams.model &&\n vehicleParams.model.engine\n ) {\n // Considering percentage values if absolute values not available and maxChargeKWH exists\n const engine = vehicleParams.model.engine;\n const maxChargeKWH = engine.charging?.maxChargeKWH;\n if (maxChargeKWH) {\n urlParams.append(\n 'minChargeAtDestinationInkWh',\n String((maxChargeKWH * pctChargingPrefs.minChargeAtDestinationPCT) / 100),\n );\n urlParams.append(\n 'minChargeAtChargingStopsInkWh',\n String((maxChargeKWH * pctChargingPrefs.minChargeAtChargingStopsPCT) / 100),\n );\n }\n }\n }\n }\n};\n\nconst appendVehicleDimensions = (urlParams: URLSearchParams, dimensions?: VehicleDimensions): void => {\n if (dimensions) {\n // (defaults are 0):\n dimensions.lengthMeters && urlParams.append('vehicleLength', String(dimensions.lengthMeters));\n dimensions.heightMeters && urlParams.append('vehicleHeight', String(dimensions.heightMeters));\n dimensions.widthMeters && urlParams.append('vehicleWidth', String(dimensions.widthMeters));\n dimensions.weightKG && urlParams.append('vehicleWeight', String(dimensions.weightKG));\n dimensions.axleWeightKG && urlParams.append('vehicleAxleWeight', String(dimensions.axleWeightKG));\n }\n};\n\nconst appendVehicleRestrictions = (urlParams: URLSearchParams, vehicleParams: VehicleParameters): void => {\n // Vehicle restrictions from VehicleRestrictions intersection:\n const restrictions = vehicleParams.restrictions;\n if (!restrictions) {\n return;\n }\n\n appendByRepeatingParamName(urlParams, 'vehicleLoadType', restrictions.loadTypes);\n restrictions.adrCode && urlParams.append('vehicleAdrTunnelRestrictionCode', restrictions.adrCode);\n restrictions.commercial && urlParams.append('vehicleCommercial', String(restrictions.commercial));\n // (default is 0):\n restrictions.maxSpeedKMH && urlParams.append('vehicleMaxSpeed', String(restrictions.maxSpeedKMH));\n};\n\nconst appendVehicleEngineModel = (\n urlParams: URLSearchParams,\n engineType: VehicleEngineType,\n engine: VehicleEngineModel<VehicleEngineType>,\n): void => {\n // (efficiency params have the same names between engine types)\n appendConsumptionEfficiency(urlParams, engine.consumption.efficiency);\n\n if (engineType === 'electric') {\n appendElectricConsumptionModel(urlParams, (engine as ElectricEngineModel).consumption);\n appendChargingModel(urlParams, engine as ElectricEngineModel);\n } else {\n // (no need to append combustion vehicleEngineType since it's the default)\n appendCombustionEngine(urlParams, engine as CombustionEngineModel);\n }\n};\n\nconst appendVehicleModel = (urlParams: URLSearchParams, vehicleParams: VehicleParameters): void => {\n if (!vehicleParams.model) {\n return;\n }\n\n // Handle predefined vehicle model\n if ('variantId' in vehicleParams.model) {\n urlParams.append('vehicleModelId', vehicleParams.model.variantId);\n } else {\n // Handle explicit vehicle model (dimensions and engine)\n appendVehicleDimensions(urlParams, vehicleParams.model.dimensions);\n\n if (vehicleParams.model.engine) {\n appendVehicleEngineModel(\n urlParams,\n 'engineType' in vehicleParams ? vehicleParams.engineType : undefined,\n vehicleParams.model.engine,\n );\n }\n }\n};\n\n/**\n * Appends vehicle parameters to the URL search params for routing requests.\n * @param urlParams - The URLSearchParams to append to\n * @param vehicleParams - The vehicle parameters to append\n */\nexport const appendVehicleParams = (urlParams: URLSearchParams, vehicleParams?: VehicleParameters): void => {\n if (!vehicleParams) {\n return;\n }\n\n // the engine type defaults to combustion, thus we only bother to append it if it's electric:\n if ((vehicleParams as ElectricVehicleParams).engineType === 'electric') {\n urlParams.append('vehicleEngineType', 'electric');\n }\n\n appendVehicleModel(urlParams, vehicleParams);\n appendVehicleState(urlParams, vehicleParams);\n appendVehiclePreferences(urlParams, vehicleParams);\n appendVehicleRestrictions(urlParams, vehicleParams);\n};\n","import type { CommonRoutingParams, DepartArriveParams } from '../types/commonRoutingParams';\nimport { appendByRepeatingParamName, appendOptionalParam } from './requestBuildingUtils';\nimport { appendVehicleParams } from './routingVehicleParamsBuilder';\n\nconst appendWhenParams = (urlParams: URLSearchParams, when?: DepartArriveParams): void => {\n if (when?.date) {\n const formattedDate = when.date.toISOString();\n if (when.option === 'departAt') {\n urlParams.append('departAt', formattedDate);\n } else if (when.option === 'arriveBy') {\n urlParams.append('arriveAt', formattedDate);\n }\n }\n};\n\n// TODO: not supported yet in Orbis\n// const appendThrillingParams = (urlParams: URLSearchParams, thrillingParams?: ThrillingParams): void => {\n// if (thrillingParams) {\n// thrillingParams.hilliness && urlParams.append('hilliness', thrillingParams.hilliness);\n// thrillingParams.windingness && urlParams.append('windingness', thrillingParams.windingness);\n// }\n// };\n\n/**\n * @ignore\n */\nexport const appendCommonRoutingParams = (urlParams: URLSearchParams, params: CommonRoutingParams): void => {\n const costModel = params.costModel;\n appendByRepeatingParamName(urlParams, 'avoid', costModel?.avoid);\n appendOptionalParam(urlParams, 'traffic', costModel?.traffic);\n appendWhenParams(urlParams, params.when);\n appendOptionalParam(urlParams, 'routeType', costModel?.routeType);\n // TODO not supported in Orbis\n // if (costModel?.routeType === 'thrilling') {\n // appendThrillingParams(urlParams, costModel.thrillingParams);\n // }\n appendOptionalParam(urlParams, 'travelMode', params.travelMode);\n appendVehicleParams(urlParams, params.vehicle);\n};\n","import { getPositionStrict } from '@tomtom-org/maps-sdk/core';\nimport type { Position } from 'geojson';\nimport type { FetchInput } from '../shared';\nimport { appendCommonRoutingParams } from '../shared/request/commonRoutingRequestBuilder';\nimport { appendCommonParams, appendOptionalParam } from '../shared/request/requestBuildingUtils';\nimport type { ElectricVehicleParams } from '../shared/types/vehicleParams';\nimport type { ElectricVehicleStatePCT } from '../shared/types/vehicleState';\nimport type { ReachableRangePostData } from './types/apiRequestTypes';\nimport type { ReachableRangeParams } from './types/reachableRangeParams';\n\nconst buildUrlBasePath = (params: ReachableRangeParams): string =>\n params.customServiceBaseURL ?? `${params.commonBaseURL}/maps/orbis/routing/calculateReachableRange`;\n\nconst getMaxChargeKWH = (params: ReachableRangeParams): number | undefined => {\n const vehicle = params.vehicle as ElectricVehicleParams | undefined;\n if (!vehicle?.model || !('engine' in vehicle.model)) {\n return undefined;\n }\n return vehicle.model.engine?.charging?.maxChargeKWH;\n};\n\nconst getCurrentChargeKWH = (params: ReachableRangeParams): number | undefined => {\n const vehicle = params.vehicle as ElectricVehicleParams | undefined;\n if (!vehicle?.state) {\n return undefined;\n }\n const pctState = vehicle.state as ElectricVehicleStatePCT;\n if (pctState.currentChargePCT != null) {\n const maxChargeKWH = getMaxChargeKWH(params);\n if (maxChargeKWH != null) {\n return (maxChargeKWH * pctState.currentChargePCT) / 100;\n }\n }\n return undefined;\n};\n\nconst appendBudget = (urlParams: URLSearchParams, params: ReachableRangeParams): void => {\n const budget = params.budget;\n switch (budget.type) {\n case 'timeMinutes':\n urlParams.append('timeBudgetInSec', (budget.value * 60).toString());\n break;\n case 'distanceKM':\n urlParams.append('distanceBudgetInMeters', (budget.value * 1000).toString());\n break;\n case 'spentFuelLiters':\n urlParams.append('fuelBudgetInLiters', budget.value.toString());\n break;\n case 'spentChargePCT': {\n const maxChargeKWH = getMaxChargeKWH(params);\n if (maxChargeKWH != null) {\n urlParams.append('energyBudgetInkWh', ((maxChargeKWH * budget.value) / 100).toString());\n }\n break;\n }\n case 'remainingChargeCPT': {\n const currentChargeKWH = getCurrentChargeKWH(params);\n const maxChargeKWH = getMaxChargeKWH(params);\n if (maxChargeKWH != null && currentChargeKWH != null) {\n const remainingKWH = (maxChargeKWH * budget.value) / 100;\n urlParams.append('energyBudgetInkWh', Math.max(0, currentChargeKWH - remainingKWH).toString());\n }\n break;\n }\n default:\n // Unsupported by SDK but will attempt to send it anyway\n urlParams.append(budget.type, budget.value.toString());\n }\n};\n\nconst buildPostData = (params: ReachableRangeParams): ReachableRangePostData => {\n const position: Position = getPositionStrict(params.origin);\n return {\n origin: { type: 'Point', coordinates: [position[0], position[1]] },\n };\n};\n\n/**\n * @param params\n * @returns\n */\nexport const buildReachableRangeRequest = (params: ReachableRangeParams): FetchInput<ReachableRangePostData> => {\n const url = new URL(buildUrlBasePath(params));\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n // Currently reachable range API does not support language: https://developer.tomtom.com/routing-api/documentation/tomtom-orbis-maps/v3/calculate-reachable-range\n urlParams.delete('language');\n appendCommonRoutingParams(urlParams, params);\n appendBudget(urlParams, params);\n appendOptionalParam(urlParams, 'maxFerryLengthInMeters', params.maxFerryLengthMeters);\n appendOptionalParam(urlParams, 'smoothing', params.smoothing);\n return { method: 'POST', url, data: buildPostData(params) };\n};\n","import type { BBox, PolygonFeature } from '@tomtom-org/maps-sdk/core';\nimport { bboxFromGeoJSON } from '@tomtom-org/maps-sdk/core';\nimport type { Polygon } from 'geojson';\nimport type { ReachableRangeResponseAPI } from './types/apiResponseTypes';\nimport type { ReachableRangeParams } from './types/reachableRangeParams';\n\n/**\n *\n * @param apiResponse\n * @param params\n */\nexport const parseReachableRangeResponse = (\n apiResponse: ReachableRangeResponseAPI,\n params: ReachableRangeParams,\n): PolygonFeature<ReachableRangeParams> => {\n const geometry: Polygon = {\n type: 'Polygon',\n coordinates: [apiResponse.reachableRange.boundary.map((point) => [point.longitude, point.latitude])],\n };\n const bbox = bboxFromGeoJSON(geometry) as BBox; // the geometry should always have a bbox\n return { type: 'Feature', geometry, bbox, properties: params };\n};\n","import type { PolygonFeature } from '@tomtom-org/maps-sdk/core';\nimport { parseRoutingResponseError } from '../routing/routingResponseErrorParser';\nimport type { ServiceTemplate } from '../shared';\nimport { fetchWith } from '../shared/fetch';\nimport { reachableRangeRequestValidationConfig } from './reachableRangeRequestSchema';\nimport { buildReachableRangeRequest } from './requestBuilder';\nimport { parseReachableRangeResponse } from './responseParser';\nimport type { ReachableRangeRequestAPI } from './types/apiRequestTypes';\nimport type { ReachableRangeResponseAPI } from './types/apiResponseTypes';\nimport type { ReachableRangeParams } from './types/reachableRangeParams';\n\nexport type ReachableRangeTemplate = ServiceTemplate<\n ReachableRangeParams,\n ReachableRangeRequestAPI,\n ReachableRangeResponseAPI,\n PolygonFeature<ReachableRangeParams>\n>;\n\nexport const reachableRangeTemplate: ReachableRangeTemplate = {\n requestValidation: reachableRangeRequestValidationConfig,\n buildRequest: buildReachableRangeRequest,\n sendRequest: fetchWith,\n parseResponse: parseReachableRangeResponse,\n parseResponseError: parseRoutingResponseError,\n getAPIVersion: () => 3,\n};\n","import type { ReachableRangeTemplate } from './reachableRangeTemplate';\nimport { reachableRangeTemplate } from './reachableRangeTemplate';\nimport { buildReachableRangeRequest } from './requestBuilder';\nimport { parseReachableRangeResponse } from './responseParser';\n\nconst customize: {\n buildReachableRangeRequest: typeof buildReachableRangeRequest;\n parseReachableRangeResponse: typeof parseReachableRangeResponse;\n reachableRangeTemplate: ReachableRangeTemplate;\n} = {\n buildReachableRangeRequest,\n parseReachableRangeResponse,\n reachableRangeTemplate,\n};\nexport default customize;\n","import { getPositionStrict } from '@tomtom-org/maps-sdk/core';\nimport { isNil } from 'lodash-es';\nimport type { CommonServiceParams } from '../shared';\nimport { arrayToCSV } from '../shared/arrays';\nimport { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport { appendCommonParams } from '../shared/request/requestBuildingUtils';\nimport type { ReverseGeocodingParams } from './types/reverseGeocodingParams';\n\nconst buildUrlBasePath = (params: CommonServiceParams): string =>\n params.customServiceBaseURL || `${params.commonBaseURL}${PLACES_URL_PATH}/reverseGeocode`;\n\n/**\n * Default function for building a reverse geocoding request from {@link ReverseGeocodingParams}\n * @param params The reverse geocoding parameters, with global configuration already merged into them.\n */\nexport const buildRevGeoRequest = (params: ReverseGeocodingParams): URL => {\n const lngLat = getPositionStrict(params.position);\n const url = new URL(`${buildUrlBasePath(params)}/${lngLat[1]},${lngLat[0]}.json`);\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n\n // rev-geo specific parameters:\n params.allowFreeformNewline && urlParams.append('allowFreeformNewline', String(params.allowFreeformNewline));\n params.geographyType && urlParams.append('entityType', arrayToCSV(params.geographyType));\n !isNil(params.heading) && urlParams.append('heading', String(params.heading));\n params.mapcodes && urlParams.append('mapcodes', arrayToCSV(params.mapcodes));\n params.number && urlParams.append('number', params.number);\n !isNil(params.radiusMeters) && urlParams.append('radius', String(params.radiusMeters));\n params.returnSpeedLimit && urlParams.append('returnSpeedLimit', String(params.returnSpeedLimit));\n params.returnRoadUse && urlParams.append('returnRoadUse', String(params.returnRoadUse));\n params.roadUses && urlParams.append('roadUse', JSON.stringify(params.roadUses));\n return url;\n};\n","import { generateId, getPositionStrict, toPointGeometry } from '@tomtom-org/maps-sdk/core';\nimport { apiToGeoJSONBBox, csvLatLngToPosition } from '../shared/geometry';\nimport type { ReverseGeocodingResponse } from './reverseGeocoding';\nimport type { ReverseGeocodingResponseAPI } from './types/apiTypes';\nimport type { ReverseGeocodingParams } from './types/reverseGeocodingParams';\n\n/**\n * Default method for parsing reverse geocoding request from {@link ReverseGeocodingResponse}\n * @param params\n * @param apiResponse\n */\nexport const parseRevGeoResponse = (\n apiResponse: ReverseGeocodingResponseAPI,\n params: ReverseGeocodingParams,\n): ReverseGeocodingResponse => {\n const firstApiResult = apiResponse.addresses[0];\n const { boundingBox, sideOfStreet, offsetPosition, ...address } = firstApiResult?.address || {};\n return {\n type: 'Feature',\n // The requested coordinates are the primary ones, and set as the GeoJSON Feature geometry:\n geometry: toPointGeometry(getPositionStrict(params.position)),\n ...(boundingBox && { bbox: apiToGeoJSONBBox(boundingBox) }),\n id: generateId(),\n ...(firstApiResult && {\n properties: {\n type: firstApiResult?.entityType ? 'Geography' : !address.streetNumber ? 'Street' : 'Point Address',\n address,\n ...(firstApiResult.dataSources && { dataSources: firstApiResult.dataSources }),\n ...(firstApiResult.mapcodes && { mapcodes: firstApiResult.mapcodes }),\n ...(sideOfStreet && { sideOfStreet }),\n ...(offsetPosition && { offsetPosition: csvLatLngToPosition(offsetPosition) }),\n // The reverse geocoded coordinates are secondary and set in the GeoJSON properties:\n originalPosition: csvLatLngToPosition(firstApiResult.position),\n },\n }),\n };\n};\n","import { views } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { hasLngLatSchema } from '../shared/schema/geometriesSchema';\n\nconst revGeocodeRequestMandatory = z.object({\n position: hasLngLatSchema.describe('Geographic position [longitude, latitude] to reverse geocode'),\n});\n\nconst revGeocodeRequestOptional = z.object({\n allowFreeformNewline: z.boolean().optional().describe('Allow newline characters in freeform address'),\n geographyType: z.array(z.string()).optional().describe('Filter results to specific geography types'),\n heading: z\n .number()\n .min(-360)\n .max(360)\n .optional()\n .describe('Vehicle heading in degrees (-360 to 360) for directional results'),\n mapcodes: z.array(z.string()).optional().describe('Request mapcode representations for location'),\n number: z.string().optional().describe('Street number for more precise address results'),\n radiusMeters: z.number().optional().describe('Search radius in meters for reverse geocoding'),\n returnMatchType: z.boolean().optional().describe('Include match type information in response'),\n returnRoadUse: z.boolean().optional().describe('Include road use information in response'),\n returnSpeedLimit: z.boolean().optional().describe('Include speed limit information in response'),\n roadUses: z.array(z.string()).optional().describe('Filter results to specific road use types'),\n view: z.enum(views).optional().describe('Geopolitical view for disputed territories'),\n});\n\n/**\n * @ignore\n */\nexport const revGeocodeRequestSchema = revGeocodeRequestMandatory.extend(revGeocodeRequestOptional.shape);\n","import type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { buildRevGeoRequest } from './requestBuilder';\nimport { parseRevGeoResponse } from './responseParser';\nimport type { ReverseGeocodingResponse } from './reverseGeocoding';\nimport { revGeocodeRequestSchema } from './revGeocodeRequestSchema';\nimport type { ReverseGeocodingResponseAPI } from './types/apiTypes';\nimport type { ReverseGeocodingParams } from './types/reverseGeocodingParams';\n\n/**\n * Reverse Geocoding service template type.\n * @ignore\n */\nexport type ReverseGeocodingTemplate = ServiceTemplate<\n ReverseGeocodingParams,\n URL,\n ReverseGeocodingResponseAPI,\n ReverseGeocodingResponse\n>;\n\n/**\n * Reverse Geocoding service template main implementation.\n * @ignore\n */\nexport const reverseGeocodingTemplate: ReverseGeocodingTemplate = {\n requestValidation: { schema: revGeocodeRequestSchema },\n buildRequest: buildRevGeoRequest,\n sendRequest: get,\n parseResponse: parseRevGeoResponse,\n};\n","import { buildRevGeoRequest } from './requestBuilder';\nimport { parseRevGeoResponse } from './responseParser';\nimport type { ReverseGeocodingTemplate } from './reverseGeocodingTemplate';\nimport { reverseGeocodingTemplate } from './reverseGeocodingTemplate';\n\nconst customize: {\n buildRevGeoRequest: typeof buildRevGeoRequest;\n parseRevGeoResponse: typeof parseRevGeoResponse;\n reverseGeocodingTemplate: ReverseGeocodingTemplate;\n} = {\n buildRevGeoRequest,\n parseRevGeoResponse,\n reverseGeocodingTemplate,\n};\nexport default customize;\n","import type { SectionType } from '@tomtom-org/maps-sdk/core';\nimport { getRoutePlanningLocationType, inputSectionTypesWithGuidance } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { commonRoutingRequestSchema } from '../shared/schema/commonRoutingRequestSchema';\nimport {\n featureSchema,\n geometrySchema,\n hasLngLatSchema,\n lineStringCoordsSchema,\n} from '../shared/schema/geometriesSchema';\nimport type { SchemaRefinement } from '../shared/types/validation';\nimport type { CalculateRouteParams } from './types/calculateRouteParams';\n\nconst waypointLikeSchema = z.union([hasLngLatSchema, geometrySchema]).describe('Waypoint as position or geometry');\nconst pathLikeSchema = z\n .union([lineStringCoordsSchema, featureSchema])\n .describe('Path as line string coordinates or feature');\n\nconst mandatorySchema = z.object({\n locations: z\n .array(z.union([waypointLikeSchema, pathLikeSchema]))\n .min(1)\n .describe('Array of route locations (waypoints or paths) - minimum 2 waypoints or 1 path required'), // see calculateRouteLocationsRefinement\n});\n\nconst optionalSchema = z.object({\n computeAdditionalTravelTimeFor: z\n .enum(['none', 'all'])\n .optional()\n .describe('Calculate additional travel time estimates for different traffic scenarios (none or all)'),\n vehicleHeading: z\n .number()\n .min(0)\n .max(359.5)\n .optional()\n .describe('Vehicle heading in degrees (0-359.5) at departure'),\n // TODO add proper instructionsInfo check\n // instructionsType: z.enum(instructionsTypes),\n maxAlternatives: z\n .number()\n .min(0)\n .max(5)\n .optional()\n .describe('Maximum number of alternative routes to calculate (0-5)'),\n sectionTypes: z\n .array(z.enum(inputSectionTypesWithGuidance as [SectionType, ...SectionType[]]))\n .optional()\n .describe('Types of route sections to include in response (toll, ferry, traffic, etc.)'),\n});\n\nconst schema = commonRoutingRequestSchema.extend(mandatorySchema.extend(optionalSchema.shape).shape);\n\nconst locationsRefinement: SchemaRefinement<CalculateRouteParams> = {\n check: (data: CalculateRouteParams): boolean => {\n const routePlanningLocationTypes = data.locations.map(getRoutePlanningLocationType);\n if (!routePlanningLocationTypes.includes('path')) {\n return data.locations.length >= 2;\n }\n return true; // see calculateRouteRequestSchemaMandatory\n },\n message:\n 'When passing waypoints only: at least 2 must be defined. ' +\n 'If passing also paths, at least one path must be defined',\n};\n\n/**\n * @ignore\n */\nexport const routeRequestValidationConfig = { schema, refinements: [locationsRefinement] };\n","import type {\n GetPositionEntryPointOption,\n PathLike,\n RoutePlanningLocation,\n RoutePlanningLocationType,\n Waypoint,\n WaypointLike,\n WaypointProps,\n} from '@tomtom-org/maps-sdk/core';\nimport {\n getPositionStrict,\n getRoutePlanningLocationType,\n inputSectionTypes,\n inputSectionTypesWithGuidance,\n} from '@tomtom-org/maps-sdk/core';\nimport type { Position } from 'geojson';\nimport { isNil, omit } from 'lodash-es';\nimport type { FetchInput } from '../shared';\nimport { VehiclePreferences } from '../shared';\nimport { positionToCSVLatLon } from '../shared/geometry';\nimport { appendCommonRoutingParams } from '../shared/request/commonRoutingRequestBuilder';\nimport {\n appendByRepeatingParamName,\n appendCommonParams,\n appendOptionalParam,\n} from '../shared/request/requestBuildingUtils';\nimport { ExplicitVehicleModel } from '../shared/types/vehicleModel';\nimport type { CalculateRoutePOSTDataAPI, PointWaypointAPI } from './types/apiRequestTypes';\nimport type { LatitudeLongitudePointAPI } from './types/apiResponseTypes';\nimport type { CalculateRouteParams, GuidanceParams, InputSectionTypes } from './types/calculateRouteParams';\n\n// Are these params about Long Distance EV Routing:\nconst getChargingPreferences = (params: CalculateRouteParams) =>\n (params.vehicle?.preferences as VehiclePreferences<'electric'>)?.chargingPreferences;\n\nconst buildUrlBasePath = (params: CalculateRouteParams): string =>\n params.customServiceBaseURL ||\n `${params.commonBaseURL}/maps/orbis/routing/${getChargingPreferences(params) ? 'calculateLongDistanceEVRoute' : 'calculateRoute'}`;\n\nconst getWaypointProps = (waypointInput: WaypointLike): WaypointProps | null =>\n (waypointInput as Waypoint).properties || null;\n\nconst defaultUseEntryPointOption: GetPositionEntryPointOption = 'main-when-available';\n\nconst buildLocationsStringFromWaypoints = (\n waypointInputs: WaypointLike[],\n useEntryPoint: GetPositionEntryPointOption,\n): string =>\n waypointInputs\n .map((waypointInput: WaypointLike) => {\n const lngLatString = positionToCSVLatLon(getPositionStrict(waypointInput, { useEntryPoint }));\n const radius = getWaypointProps(waypointInput)?.radiusMeters;\n return radius ? `circle(${lngLatString},${radius})` : lngLatString;\n })\n .join(':');\n\nconst getPositionsFromPath = (pathLike: PathLike): Position[] => {\n if (Array.isArray(pathLike)) {\n return pathLike;\n }\n return pathLike.geometry.coordinates;\n};\n\nconst getFirstAndLastPoints = (\n locations: RoutePlanningLocation[],\n types: RoutePlanningLocationType[],\n useEntryPoint: GetPositionEntryPointOption,\n): [Position, Position] => {\n let firstPoint;\n const firstRoutePlanningLocation = locations[0];\n if (types[0] === 'path') {\n const positions = getPositionsFromPath(firstRoutePlanningLocation as PathLike);\n firstPoint = positions[0];\n } else {\n firstPoint = getPositionStrict(firstRoutePlanningLocation as WaypointLike, { useEntryPoint });\n }\n\n const lastRoutePlanningLocation = locations[locations.length - 1];\n let lastPoint;\n if (types[types.length - 1] === 'path') {\n const positions = getPositionsFromPath(lastRoutePlanningLocation as PathLike);\n lastPoint = positions[positions.length - 1];\n } else {\n lastPoint = getPositionStrict(lastRoutePlanningLocation as WaypointLike, { useEntryPoint });\n }\n\n return [firstPoint, lastPoint];\n};\n\nconst buildLocationsString = (\n locations: RoutePlanningLocation[],\n routePlanningLocationTypes: RoutePlanningLocationType[],\n useEntryPoint: GetPositionEntryPointOption,\n): string =>\n buildLocationsStringFromWaypoints(\n routePlanningLocationTypes.includes('path')\n ? getFirstAndLastPoints(locations, routePlanningLocationTypes, useEntryPoint)\n : (locations as WaypointLike[]),\n useEntryPoint,\n );\n\nconst appendSectionTypes = (\n urlParams: URLSearchParams,\n sectionTypes: InputSectionTypes | undefined,\n instructionsInclude: boolean,\n): void => {\n const effectiveSectionTypes = (\n sectionTypes ?? (instructionsInclude ? inputSectionTypesWithGuidance : inputSectionTypes)\n ).map((sectionType) => (sectionType === 'vehicleRestricted' ? 'travelMode' : sectionType));\n appendByRepeatingParamName(urlParams, 'sectionType', effectiveSectionTypes);\n};\n\nconst appendGuidanceParams = (urlParams: URLSearchParams, params?: CalculateRouteParams): void => {\n if (params?.guidance) {\n const guidance: GuidanceParams = params.guidance;\n urlParams.append('instructionsType', guidance.type);\n urlParams.append('guidanceVersion', String(guidance.version ?? 2));\n urlParams.append('instructionPhonetics', guidance.phonetics ?? 'IPA');\n urlParams.append('language', params.language ?? 'en-US');\n }\n};\n\nconst toLatLngPointApi = (position: Position): LatitudeLongitudePointAPI => ({\n latitude: position[1],\n longitude: position[0],\n});\n\n// appends a path into the given post data, adding to supportingPoints and pointWaypoints as applicable\nconst appendPathPostData = (\n pathRoutePlanningLocation: PathLike,\n routePlanningLocationIndex: number,\n locations: RoutePlanningLocation[],\n supportingPoints: LatitudeLongitudePointAPI[],\n pointWaypoints: PointWaypointAPI[],\n): void => {\n // first, we add the supportingPoints from the path coordinates:\n const supportingPointsLengthBeforePath = supportingPoints.length;\n for (const position of getPositionsFromPath(pathRoutePlanningLocation)) {\n supportingPoints.push(toLatLngPointApi(position));\n }\n // then we check if it's a route, and if so we add waypoints from its legs as applicable\n // (a route leg is the portion of the path between 2 waypoints)\n if (!Array.isArray(pathRoutePlanningLocation)) {\n const legs = pathRoutePlanningLocation.properties.sections.leg;\n // (We assume all routes have at least 1 leg)\n legs.forEach((leg, legIndex) => {\n // If the route is the first geo-input, we skip adding the leg...\n // ... since it's expected to be already in the origin \"location\"\n if (routePlanningLocationIndex > 0 || legIndex > 0) {\n pointWaypoints.push({\n supportingPointIndex: supportingPointsLengthBeforePath + (leg.startPointIndex as number),\n waypointSourceType: 'USER_DEFINED',\n });\n }\n });\n // If the route isn't the last geo-input, we add its destination as pointWaypoint too:\n // (If it's the last geo-input, we skip adding the leg...\n // ... since it's expected to be already in the destination \"location\")\n if (routePlanningLocationIndex < locations.length - 1) {\n pointWaypoints.push({\n supportingPointIndex:\n supportingPointsLengthBeforePath + pathRoutePlanningLocation.geometry.coordinates.length - 1,\n waypointSourceType: 'USER_DEFINED',\n });\n }\n }\n};\n\n// appends a waypoint into the given post data, adding to supportingPoints and pointWaypoints as applicable\nconst appendWaypointPostData = (\n waypoint: WaypointLike,\n routePlanningLocationIndex: number,\n locations: RoutePlanningLocation[],\n supportingPoints: LatitudeLongitudePointAPI[],\n pointWaypoints: PointWaypointAPI[],\n useEntryPoint: GetPositionEntryPointOption,\n) => {\n // individual points are treated like POST waypoints\n supportingPoints.push(toLatLngPointApi(getPositionStrict(waypoint, { useEntryPoint })));\n // for origin and destination we do not add pointWaypoints, since they end up as the URL \"locations\":\n if (routePlanningLocationIndex > 0 && routePlanningLocationIndex < locations.length - 1) {\n pointWaypoints.push({\n supportingPointIndex: supportingPoints.length - 1,\n waypointSourceType: 'USER_DEFINED',\n });\n }\n};\n\nconst buildlocationsPostData = (\n locations: RoutePlanningLocation[],\n types: RoutePlanningLocationType[],\n useEntryPoints: GetPositionEntryPointOption,\n): { supportingPoints: LatitudeLongitudePointAPI[]; pointWaypoints?: PointWaypointAPI[] } => {\n const supportingPoints: LatitudeLongitudePointAPI[] = [];\n const pointWaypoints: PointWaypointAPI[] = [];\n\n locations.forEach((routePlanningLocation, routePlanningLocationIndex) => {\n if (types[routePlanningLocationIndex] === 'path') {\n appendPathPostData(\n routePlanningLocation as PathLike,\n routePlanningLocationIndex,\n locations,\n supportingPoints,\n pointWaypoints,\n );\n } else {\n appendWaypointPostData(\n routePlanningLocation as WaypointLike,\n routePlanningLocationIndex,\n locations,\n supportingPoints,\n pointWaypoints,\n useEntryPoints,\n );\n }\n });\n\n return { supportingPoints, ...(pointWaypoints.length && { pointWaypoints }) };\n};\n\nconst buildPostData = (\n params: CalculateRouteParams,\n types: RoutePlanningLocationType[],\n useEntryPoints: GetPositionEntryPointOption,\n): CalculateRoutePOSTDataAPI | null => {\n const pathsIncluded = types.includes('path');\n const isLdevr = !!getChargingPreferences(params);\n if (!pathsIncluded && !isLdevr) {\n // (if no paths in the given locations nor LDEVR, there'll be no POST data, which will trigger a GET call)\n return null;\n }\n\n const vehicleModel = params.vehicle?.model as ExplicitVehicleModel<'electric'>;\n const chargingModel = vehicleModel?.engine?.charging;\n return {\n ...(pathsIncluded && buildlocationsPostData(params.locations, types, useEntryPoints)),\n ...(isLdevr &&\n chargingModel && {\n chargingParameters: omit(chargingModel, 'maxChargeKWH'),\n }),\n };\n};\n\n/**\n * Default function for building calculate route request from {@link CalculateRouteParams}\n * @param params The calculate route parameters, with global configuration already merged into them.\n */\nexport const buildCalculateRouteRequest = (params: CalculateRouteParams): FetchInput<CalculateRoutePOSTDataAPI> => {\n const routePlanningLocationTypes = params.locations.map(getRoutePlanningLocationType);\n const useEntryPoints = params.useEntryPoints ?? defaultUseEntryPointOption;\n const url = new URL(\n `${buildUrlBasePath(params)}/${buildLocationsString(params.locations, routePlanningLocationTypes, useEntryPoints)}/json`,\n );\n const urlParams: URLSearchParams = url.searchParams;\n appendCommonParams(urlParams, params);\n if (!('language' in params)) {\n // for routing we ensure to always have a default language input since by default we fetch some language-specific sections:\n // (see importantRoadStretch as default, and instructionsType when guidance is provided)\n // It's still possible to force the language to be undefined if skipping such sections for performance reasons\n urlParams.append('language', 'en-GB');\n }\n appendCommonRoutingParams(urlParams, params);\n appendOptionalParam(urlParams, 'computeTravelTimeFor', params.computeAdditionalTravelTimeFor);\n appendGuidanceParams(urlParams, params);\n !isNil(params.maxAlternatives) && urlParams.append('maxAlternatives', String(params.maxAlternatives));\n appendSectionTypes(urlParams, params.sectionTypes, !!params.guidance?.type);\n for (const representation of params.extendedRouteRepresentations ?? ['distance', 'travelTime']) {\n urlParams.append('extendedRouteRepresentation', representation);\n }\n\n const postData = buildPostData(params, routePlanningLocationTypes, useEntryPoints);\n return postData ? { method: 'POST', url, data: postData } : { method: 'GET', url };\n};\n","import {\n BBox,\n bboxFromGeoJSON,\n type ChargingStop,\n type CountrySectionProps,\n type CurrentType,\n type Guidance,\n generateId,\n type ImportantRoadStretchProps,\n type Instruction,\n indexedMagnitudes,\n type LaneDirection,\n type LaneSectionProps,\n type LegSectionProps,\n type LegSummary,\n type PossibleLaneSeparator,\n type RoadShieldReference,\n type RoadShieldSectionProps,\n type Route,\n type RouteSummary,\n type Routes,\n type SectionProps,\n type SectionsProps,\n type SectionType,\n type SpeedLimitSectionProps,\n type TrafficIncidentCategory,\n type TrafficIncidentTEC,\n type TrafficSectionProps,\n} from '@tomtom-org/maps-sdk/core';\nimport type { LineString, Position } from 'geojson';\nimport { isNil, omit } from 'lodash-es';\nimport { toChargingSpeed } from '../shared/ev';\nimport { ExplicitVehicleModel } from '../shared/types/vehicleModel';\nimport {\n CalculateRouteResponseAPI,\n ChargingStopAPI,\n CurrentTypeAPI,\n GuidanceAPI,\n LegAPI,\n RouteAPI,\n RoutePathPointAPI,\n SectionAPI,\n SummaryAPI,\n} from './types/apiResponseTypes';\nimport { CalculateRouteParams } from './types/calculateRouteParams';\n\nconst toCurrentType = (apiCurrentType: CurrentTypeAPI): CurrentType | undefined => {\n switch (apiCurrentType) {\n case 'Direct_Current':\n return 'DC';\n case 'Alternating_Current_1_Phase':\n return 'AC1';\n case 'Alternating_Current_3_Phase':\n return 'AC3';\n default:\n return undefined;\n }\n};\n\nconst toChargingStop = (\n chargingInformationAtEndOfLeg: ChargingStopAPI,\n maxChargeKWH: number | undefined,\n): ChargingStop => {\n const chargingConnectionInfo = chargingInformationAtEndOfLeg.chargingConnectionInfo;\n const chargingParkLocation = chargingInformationAtEndOfLeg.chargingParkLocation;\n const coordinates = [chargingParkLocation.coordinate.longitude, chargingParkLocation.coordinate.latitude];\n\n // Build freeformAddress from available components\n const addressParts = [chargingParkLocation.street, chargingParkLocation.houseNumber].filter(Boolean);\n const freeformAddress = addressParts.length > 0 ? addressParts.join(', ') : '';\n\n return {\n type: 'Feature',\n id: chargingInformationAtEndOfLeg.chargingParkId,\n geometry: { type: 'Point', coordinates },\n properties: {\n ...omit(chargingInformationAtEndOfLeg, ['chargingConnectionInfo', 'chargingParkLocation']),\n type: 'POI',\n address: {\n freeformAddress,\n ...(chargingParkLocation.street && { streetName: chargingParkLocation.street }),\n ...(chargingParkLocation.houseNumber && { streetNumber: chargingParkLocation.houseNumber }),\n ...(chargingParkLocation.city && { municipality: chargingParkLocation.city }),\n ...(chargingParkLocation.region && { countrySubdivision: chargingParkLocation.region }),\n ...(chargingParkLocation.postalCode && { postalCode: chargingParkLocation.postalCode }),\n ...(chargingParkLocation.country && { country: chargingParkLocation.country }),\n },\n ...(chargingConnectionInfo && {\n chargingConnectionInfo: {\n plugType: chargingConnectionInfo.chargingPlugType,\n currentInA: chargingConnectionInfo.chargingCurrentInA,\n voltageInV: chargingConnectionInfo.chargingVoltageInV,\n chargingPowerInkW: chargingConnectionInfo.chargingPowerInkW,\n currentType: toCurrentType(chargingConnectionInfo.chargingCurrentType),\n chargingSpeed: toChargingSpeed(chargingConnectionInfo.chargingPowerInkW),\n },\n }),\n ...(maxChargeKWH && {\n targetChargeInPCT: (100 * chargingInformationAtEndOfLeg.targetChargeInkWh) / maxChargeKWH,\n }),\n ...(chargingInformationAtEndOfLeg.chargingParkPowerInkW && {\n chargingParkSpeed: toChargingSpeed(chargingInformationAtEndOfLeg.chargingParkPowerInkW),\n }),\n },\n };\n};\n\nconst parseSummary = (apiSummary: SummaryAPI, params: CalculateRouteParams): RouteSummary | LegSummary => {\n const maxChargeKWH = (params?.vehicle?.model as ExplicitVehicleModel<'electric'>)?.engine?.charging?.maxChargeKWH;\n return {\n lengthInMeters: apiSummary.lengthInMeters,\n historicTrafficTravelTimeInSeconds: apiSummary.historicTrafficTravelTimeInSeconds,\n liveTrafficIncidentsTravelTimeInSeconds: apiSummary.liveTrafficIncidentsTravelTimeInSeconds,\n noTrafficTravelTimeInSeconds: apiSummary.noTrafficTravelTimeInSeconds,\n trafficDelayInSeconds: apiSummary.trafficDelayInSeconds,\n trafficLengthInMeters: apiSummary.trafficLengthInMeters,\n travelTimeInSeconds: apiSummary.travelTimeInSeconds,\n departureTime: new Date(apiSummary.departureTime),\n arrivalTime: new Date(apiSummary.arrivalTime),\n deviationDistanceInMeters: apiSummary.deviationDistance,\n fuelConsumptionInLiters: apiSummary.fuelConsumptionInLiters,\n ...(apiSummary.deviationPoint && {\n deviationPoint: [apiSummary.deviationPoint.longitude, apiSummary.deviationPoint.latitude],\n }),\n // EV-specific fields:\n totalChargingTimeInSeconds: apiSummary.totalChargingTimeInSeconds,\n batteryConsumptionInkWh: apiSummary.batteryConsumptionInkWh,\n ...(maxChargeKWH &&\n apiSummary.batteryConsumptionInkWh && {\n batteryConsumptionInPCT: (100 * apiSummary.batteryConsumptionInkWh) / maxChargeKWH,\n }),\n remainingChargeAtArrivalInkWh: apiSummary.remainingChargeAtArrivalInkWh,\n ...(maxChargeKWH &&\n apiSummary.remainingChargeAtArrivalInkWh && {\n remainingChargeAtArrivalInPCT: (100 * apiSummary.remainingChargeAtArrivalInkWh) / maxChargeKWH,\n }),\n ...(apiSummary.chargingInformationAtEndOfLeg && {\n chargingInformationAtEndOfLeg: toChargingStop(apiSummary.chargingInformationAtEndOfLeg, maxChargeKWH),\n }),\n };\n};\n\nconst parseRoutePath = (apiRouteLegs: LegAPI[]): LineString => ({\n type: 'LineString',\n coordinates: apiRouteLegs.flatMap((apiLeg) =>\n apiLeg.points?.map((apiPoint) => [apiPoint.longitude, apiPoint.latitude]),\n ),\n});\n\nconst parseLegSectionProps = (apiLegs: LegAPI[], params: CalculateRouteParams): LegSectionProps[] =>\n apiLegs.reduce<LegSectionProps[]>((accumulatedParsedLegs, nextApiLeg, currentIndex) => {\n const lastLegEndPointIndex = currentIndex === 0 ? 0 : accumulatedParsedLegs[currentIndex - 1]?.endPointIndex;\n let endPointIndex;\n if (!isNil(lastLegEndPointIndex)) {\n if (lastLegEndPointIndex === 0) {\n // in case of first or only leg, we reduce the length by one to be consistent with other sections\n // endPointIndex is inclusive\n endPointIndex = nextApiLeg.points?.length > 0 ? nextApiLeg.points.length - 1 : 0;\n } else {\n endPointIndex = lastLegEndPointIndex + nextApiLeg.points?.length;\n }\n }\n accumulatedParsedLegs.push({\n ...(!isNil(lastLegEndPointIndex) && { startPointIndex: lastLegEndPointIndex }),\n ...(endPointIndex && { endPointIndex }),\n summary: parseSummary(nextApiLeg.summary, params),\n id: generateId(),\n });\n return accumulatedParsedLegs;\n }, []);\n\nconst toSectionProps = (apiSection: SectionAPI): SectionProps => ({\n id: generateId(),\n startPointIndex: apiSection.startPointIndex,\n endPointIndex: apiSection.endPointIndex,\n});\n\nconst toRoadStretchSectionProps = (apiSection: SectionAPI): ImportantRoadStretchProps => ({\n ...toSectionProps(apiSection),\n index: apiSection.importantRoadStretchIndex as number,\n streetName: apiSection.streetName?.text,\n roadNumbers: apiSection.roadNumbers?.map((roadNumber) => roadNumber.text),\n});\n\nconst toCountrySectionProps = (apiSection: SectionAPI): CountrySectionProps => ({\n ...toSectionProps(apiSection),\n countryCodeISO3: apiSection.countryCode as string,\n});\n\nconst toVehicleRestrictedSectionProps = (apiSection: SectionAPI): SectionProps | null =>\n apiSection.travelMode === 'other' ? toSectionProps(apiSection) : null;\n\nconst calculateTrafficCategory = (tecMainCauseCode: number | undefined): TrafficIncidentCategory => {\n switch (tecMainCauseCode) {\n case 1:\n return 'jam';\n case 2:\n return 'accident';\n case 3:\n return 'roadworks';\n case 4:\n return 'narrow-lanes';\n case 5:\n return 'road-closed';\n case 9:\n return 'danger';\n case 11:\n return 'animals-on-road';\n case 13:\n return 'broken-down-vehicle';\n case 16:\n return 'lane-closed';\n case 17:\n return 'wind';\n case 18:\n return 'fog';\n case 19:\n return 'rain';\n case 22:\n return 'frost';\n case 23:\n return 'flooding';\n default:\n return 'other';\n }\n};\n\n/**\n * @ignore\n */\nexport const toTrafficCategories = (apiSection: SectionAPI): TrafficIncidentCategory[] => {\n if (apiSection.tec?.causes?.length) {\n return apiSection.tec.causes.map((cause) => calculateTrafficCategory(cause.mainCauseCode));\n }\n // else\n switch (apiSection.simpleCategory) {\n case 'JAM':\n return ['jam'];\n case 'ROAD_WORK':\n return ['roadworks'];\n case 'ROAD_CLOSURE':\n return ['road-closed'];\n default:\n return ['other'];\n }\n};\n\nconst toTrafficSectionProps = (apiSection: SectionAPI): TrafficSectionProps => ({\n ...toSectionProps(apiSection),\n delayInSeconds: apiSection.delayInSeconds,\n effectiveSpeedInKmh: apiSection.effectiveSpeedInKmh,\n categories: toTrafficCategories(apiSection),\n magnitudeOfDelay: indexedMagnitudes[apiSection.magnitudeOfDelay as number],\n tec: apiSection.tec as TrafficIncidentTEC,\n});\n\nconst toLaneSectionProps = (apiSection: SectionAPI): LaneSectionProps => ({\n ...toSectionProps(apiSection),\n lanes: apiSection.lanes as LaneDirection[],\n laneSeparators: apiSection.laneSeparators as PossibleLaneSeparator[],\n properties: apiSection.properties,\n});\n\nconst toSpeedLimitSectionProps = (apiSection: SectionAPI): SpeedLimitSectionProps => ({\n ...toSectionProps(apiSection),\n maxSpeedLimitInKmh: apiSection.maxSpeedLimitInKmh as number,\n});\n\nconst toRoadShieldsSectionProps = (apiSection: SectionAPI): RoadShieldSectionProps => ({\n ...toSectionProps(apiSection),\n roadShieldReferences: apiSection.roadShieldReferences as RoadShieldReference[],\n});\n\nconst ensureInit = <S extends SectionProps>(sectionType: SectionType, result: SectionsProps): S[] => {\n if (!result[sectionType]) {\n result[sectionType] = [];\n }\n return result[sectionType] as S[];\n};\n\nconst getSectionMapping = (\n apiSection: SectionAPI,\n): { sectionType: SectionType; mappingFunction: (apiSection: SectionAPI) => SectionProps | null } => {\n switch (apiSection.sectionType) {\n case 'CAR_TRAIN':\n return { sectionType: 'carTrain', mappingFunction: toSectionProps };\n case 'COUNTRY':\n return { sectionType: 'country', mappingFunction: toCountrySectionProps };\n case 'FERRY':\n return { sectionType: 'ferry', mappingFunction: toSectionProps };\n case 'MOTORWAY':\n return { sectionType: 'motorway', mappingFunction: toSectionProps };\n case 'PEDESTRIAN':\n return { sectionType: 'pedestrian', mappingFunction: toSectionProps };\n case 'TOLL_VIGNETTE':\n return { sectionType: 'tollVignette', mappingFunction: toCountrySectionProps };\n case 'TOLL':\n return { sectionType: 'toll', mappingFunction: toSectionProps };\n case 'TRAFFIC':\n return { sectionType: 'traffic', mappingFunction: toTrafficSectionProps };\n case 'TRAVEL_MODE':\n // NOTE: vehicleRestricted sections come from TRAVEL_MODE \"other\" ones:\n return { sectionType: 'vehicleRestricted', mappingFunction: toVehicleRestrictedSectionProps };\n case 'TUNNEL':\n return { sectionType: 'tunnel', mappingFunction: toSectionProps };\n case 'UNPAVED':\n return { sectionType: 'unpaved', mappingFunction: toSectionProps };\n case 'URBAN':\n return { sectionType: 'urban', mappingFunction: toSectionProps };\n case 'CARPOOL':\n return { sectionType: 'carpool', mappingFunction: toSectionProps };\n case 'LOW_EMISSION_ZONE':\n return { sectionType: 'lowEmissionZone', mappingFunction: toSectionProps };\n case 'LANES':\n return { sectionType: 'lanes', mappingFunction: toLaneSectionProps };\n case 'SPEED_LIMIT':\n return { sectionType: 'speedLimit', mappingFunction: toSpeedLimitSectionProps };\n case 'ROAD_SHIELDS':\n return { sectionType: 'roadShields', mappingFunction: toRoadShieldsSectionProps };\n case 'IMPORTANT_ROAD_STRETCH':\n return { sectionType: 'importantRoadStretch', mappingFunction: toRoadStretchSectionProps };\n }\n};\n\nconst parseSectionsAndAppendToResult = (apiSections: SectionAPI[], result: SectionsProps): void => {\n if (!Array.isArray(apiSections)) {\n return;\n }\n\n for (const apiSection of apiSections) {\n const sectionMapping = getSectionMapping(apiSection);\n const mappedSection = sectionMapping?.mappingFunction(apiSection);\n if (mappedSection) {\n ensureInit(sectionMapping.sectionType, result).push(mappedSection);\n }\n }\n};\n\nconst parseSections = (apiRoute: RouteAPI, params: CalculateRouteParams): SectionsProps => {\n const result = {\n leg: parseLegSectionProps(apiRoute.legs, params),\n // (the rest of sections are parsed below)\n } as SectionsProps;\n parseSectionsAndAppendToResult(apiRoute.sections, result);\n return result;\n};\n\nconst DELTA = 0.0001;\n\nconst similar = (a: Position, b: Position): boolean => Math.abs(a[0] - b[0]) < DELTA && Math.abs(a[1] - b[1]) < DELTA;\n\nconst parseGuidance = (apiGuidance: GuidanceAPI, path: Position[]): Guidance => {\n const instructions: Instruction[] = [];\n let lastInstructionPathIndex = 0;\n\n for (const apiInstruction of apiGuidance.instructions) {\n const maneuverPoint = [apiInstruction.maneuverPoint.longitude, apiInstruction.maneuverPoint.latitude];\n\n // we determine the path point index for the instruction by matching maneuverPoint to the path:\n for (let pathIndex = lastInstructionPathIndex; pathIndex < path.length; pathIndex++) {\n if (similar(path[pathIndex], maneuverPoint)) {\n lastInstructionPathIndex = pathIndex;\n break;\n }\n if (pathIndex === path.length - 1) {\n // (we do not advance lastInstructionPathIndex here to prevent missing a whole path section while mapping following instructions)\n break;\n }\n }\n instructions.push({\n ...apiInstruction,\n maneuverPoint,\n pathPointIndex: lastInstructionPathIndex,\n routePath: apiInstruction.routePath.map((apiPoint: RoutePathPointAPI) => ({\n ...apiPoint,\n point: [apiPoint.point.longitude, apiPoint.point.latitude],\n })),\n });\n }\n\n return { instructions };\n};\n\nconst parseRoute = (apiRoute: RouteAPI, index: number, params: CalculateRouteParams): Route => {\n const geometry = parseRoutePath(apiRoute.legs);\n return {\n type: 'Feature',\n geometry,\n id: generateId(),\n bbox: bboxFromGeoJSON(geometry) as BBox, // Route geometry should always have area\n properties: {\n index,\n summary: parseSummary(apiRoute.summary, params),\n sections: parseSections(apiRoute, params),\n ...(apiRoute.guidance && { guidance: parseGuidance(apiRoute.guidance, geometry.coordinates) }),\n ...(apiRoute.progress && { progress: apiRoute.progress }),\n },\n };\n};\n\n/**\n * Default method for parsing calculate route response from {@link CalculateRouteResponseAPI}\n * @param apiResponse The Routing API response.\n * @param params The params used to calculate this route.\n */\nexport const parseCalculateRouteResponse = (\n apiResponse: CalculateRouteResponseAPI,\n params: CalculateRouteParams,\n): Routes => {\n const features = apiResponse.routes.map((apiRoute, index) => parseRoute(apiRoute, index, params));\n const bbox = bboxFromGeoJSON(features);\n return { type: 'FeatureCollection', ...(bbox && { bbox }), features };\n};\n","import type { Routes } from '@tomtom-org/maps-sdk/core';\nimport type { FetchInput, ServiceTemplate } from '../shared';\nimport { fetchWith } from '../shared/fetch';\nimport { routeRequestValidationConfig } from './calculateRouteRequestSchema';\nimport { buildCalculateRouteRequest } from './requestBuilder';\nimport { parseCalculateRouteResponse } from './responseParser';\nimport { parseRoutingResponseError } from './routingResponseErrorParser';\nimport type { CalculateRoutePOSTDataAPI } from './types/apiRequestTypes';\nimport type { CalculateRouteResponseAPI } from './types/apiResponseTypes';\nimport type { CalculateRouteParams } from './types/calculateRouteParams';\n\n/**\n * @ignore\n */\nexport type CalculateRouteTemplate = ServiceTemplate<\n CalculateRouteParams,\n FetchInput<CalculateRoutePOSTDataAPI>,\n CalculateRouteResponseAPI,\n Routes\n>;\n\n/**\n * @ignore\n */\nexport const calculateRouteTemplate: CalculateRouteTemplate = {\n requestValidation: routeRequestValidationConfig,\n buildRequest: buildCalculateRouteRequest,\n sendRequest: fetchWith,\n parseResponse: parseCalculateRouteResponse,\n parseResponseError: parseRoutingResponseError,\n getAPIVersion: () => 2,\n};\n","import type { CalculateRouteTemplate } from './calculateRouteTemplate';\nimport { calculateRouteTemplate } from './calculateRouteTemplate';\nimport { buildCalculateRouteRequest } from './requestBuilder';\nimport { parseCalculateRouteResponse } from './responseParser';\n\nconst customize: {\n buildCalculateRouteRequest: typeof buildCalculateRouteRequest;\n parseCalculateRouteResponse: typeof parseCalculateRouteResponse;\n calculateRouteTemplate: CalculateRouteTemplate;\n} = {\n buildCalculateRouteRequest,\n parseCalculateRouteResponse,\n calculateRouteTemplate,\n};\nexport default customize;\n","import { bboxFromGeoJSON, trafficIncidentToIconCategory } from '@tomtom-org/maps-sdk/core';\nimport type { FetchInput } from '../shared';\nimport {\n appendByJoiningParamValue,\n appendCommonParams,\n appendOptionalParam,\n} from '../shared/request/requestBuildingUtils';\nimport type { TrafficIncidentDetailsParams } from './types/trafficIncidentDetailsParams';\n\nconst TRAFFIC_URL_PATH = '/maps/orbis/traffic';\n\n// Request all available incident fields by default so callers get a complete response without\n// having to manually specify a projection string.\nconst DEFAULT_FIELDS =\n '{incidents{type,geometry{type,coordinates},properties{id,iconCategory,magnitudeOfDelay,events{description,code,iconCategory},startTime,endTime,from,to,length,delay,roadNumbers,timeValidity,probabilityOfOccurrence,numberOfReports,lastReportTime,tmc{countryCode,tableNumber,tableVersion,direction,points{location,offset}}}}}';\n\ntype TrafficIncidentDetailsPostBody = { ids: string[] };\n\nconst buildUrlBasePath = (params: TrafficIncidentDetailsParams): string =>\n params.customServiceBaseURL ?? `${params.commonBaseURL}${TRAFFIC_URL_PATH}/incidentDetails`;\n\nconst appendOptionalParams = (urlParams: URLSearchParams, params: TrafficIncidentDetailsParams): void => {\n appendOptionalParam(urlParams, 'fields', DEFAULT_FIELDS);\n appendOptionalParam(urlParams, 't', params.trafficModelId);\n appendByJoiningParamValue(urlParams, 'categoryFilter', params.categoryFilter?.map(trafficIncidentToIconCategory));\n appendByJoiningParamValue(urlParams, 'timeValidityFilter', params.timeValidityFilter);\n};\n\n/**\n * Default method for building a traffic incident details request from {@link TrafficIncidentDetailsParams}.\n * @param params The traffic incident details parameters, with global configuration already merged into them.\n */\nexport const buildTrafficIncidentDetailsRequest = (\n params: TrafficIncidentDetailsParams,\n): FetchInput<TrafficIncidentDetailsPostBody> => {\n const url = new URL(buildUrlBasePath(params));\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n appendOptionalParams(urlParams, params);\n\n if ('bbox' in params && params.bbox) {\n const resolvedBBox = bboxFromGeoJSON(params.bbox);\n if (resolvedBBox) {\n urlParams.append('bbox', resolvedBBox.join(','));\n }\n return { method: 'GET', url };\n }\n\n // ids-based request — POST when there are more than 5 IDs (GET limit), GET otherwise\n const { ids } = params as { ids: string[] };\n\n if (ids.length > 5) {\n return { method: 'POST', url, data: { ids } };\n }\n\n urlParams.append('ids', ids.join(','));\n return { method: 'GET', url };\n};\n","import {\n iconToTrafficIncidentCategory,\n indexedMagnitudes,\n type TrafficIncident,\n type TrafficIncidentDetails,\n type TrafficIncidentEvent,\n type TrafficIncidentProbability,\n type TrafficIncidentTimeValidity,\n type TrafficIncidentTMC,\n} from '@tomtom-org/maps-sdk/core';\nimport type { IncidentAPI, IncidentDetailsResponseAPI, IncidentEventAPI, IncidentTMCAPI } from './types/apiTypes';\n\nconst parseEvent = (apiEvent: IncidentEventAPI): TrafficIncidentEvent => ({\n description: apiEvent.description,\n code: apiEvent.code,\n category: iconToTrafficIncidentCategory(apiEvent.iconCategory),\n});\n\nconst parseTMC = (apiTMC: IncidentTMCAPI): TrafficIncidentTMC => ({\n countryCode: apiTMC.countryCode,\n tableNumber: apiTMC.tableNumber,\n tableVersion: apiTMC.tableVersion,\n direction: apiTMC.direction as 'positive' | 'negative',\n points: (apiTMC.points ?? []).map((p) => ({\n location: p.location,\n ...(p.offset !== undefined && { offset: p.offset }),\n })),\n});\n\nconst parseIncident = (apiIncident: IncidentAPI): TrafficIncident => {\n const p = apiIncident.properties;\n return {\n type: 'Feature',\n geometry: apiIncident.geometry,\n properties: {\n id: p.id,\n category: iconToTrafficIncidentCategory(p.iconCategory),\n magnitudeOfDelay: indexedMagnitudes[p.magnitudeOfDelay] ?? 'unknown',\n events: (p.events ?? []).map(parseEvent),\n ...(p.startTime && { startTime: new Date(p.startTime) }),\n ...(p.endTime && { endTime: new Date(p.endTime) }),\n ...(p.from && { from: p.from }),\n ...(p.to && { to: p.to }),\n ...(p.length !== undefined && { lengthInMeters: p.length }),\n ...(p.delay !== undefined && { delayInSeconds: p.delay }),\n ...(p.roadNumbers && { roadNumbers: p.roadNumbers }),\n timeValidity: p.timeValidity as TrafficIncidentTimeValidity,\n ...(p.probabilityOfOccurrence && {\n probabilityOfOccurrence: p.probabilityOfOccurrence as TrafficIncidentProbability,\n }),\n ...(p.numberOfReports !== undefined && { numberOfReports: p.numberOfReports }),\n ...(p.lastReportTime && { lastReportTime: new Date(p.lastReportTime) }),\n ...(p.tmc && { tmc: parseTMC(p.tmc) }),\n },\n };\n};\n\n/**\n * Default method for parsing a traffic incident details API response.\n * @param apiResponse The raw Traffic Incident Details API response.\n */\nexport const parseTrafficIncidentDetailsResponse = (\n apiResponse: IncidentDetailsResponseAPI,\n): TrafficIncidentDetails => ({\n type: 'FeatureCollection',\n features: (apiResponse.incidents ?? []).filter((i): i is IncidentAPI => i !== null).map(parseIncident),\n});\n","import type { TrafficIncidentDetails } from '@tomtom-org/maps-sdk/core';\nimport type { FetchInput, ServiceTemplate } from '../shared';\nimport { fetchWith } from '../shared/fetch';\nimport { buildTrafficIncidentDetailsRequest } from './requestBuilder';\nimport { parseTrafficIncidentDetailsResponse } from './responseParser';\nimport { trafficIncidentDetailsRequestSchema } from './trafficIncidentDetailsRequestSchema';\nimport type { IncidentDetailsResponseAPI } from './types/apiTypes';\nimport type { TrafficIncidentDetailsParams } from './types/trafficIncidentDetailsParams';\n\ntype TrafficIncidentDetailsPostBody = { ids: string[] };\n\n/**\n * Traffic Incident Details service template type.\n * @ignore\n */\nexport type TrafficIncidentDetailsTemplate = ServiceTemplate<\n TrafficIncidentDetailsParams,\n FetchInput<TrafficIncidentDetailsPostBody>,\n IncidentDetailsResponseAPI,\n TrafficIncidentDetails\n>;\n\n/**\n * Traffic Incident Details service template main implementation.\n * @ignore\n */\nexport const trafficIncidentDetailsTemplate: TrafficIncidentDetailsTemplate = {\n requestValidation: { schema: trafficIncidentDetailsRequestSchema },\n buildRequest: buildTrafficIncidentDetailsRequest,\n sendRequest: fetchWith,\n parseResponse: parseTrafficIncidentDetailsResponse,\n};\n","import { trafficIncidentCategories } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { commonServiceRequestSchema } from '../shared/schema/commonParamsSchema';\nimport { hasBBoxSchema } from '../shared/schema/geometriesSchema';\n\n/**\n * @ignore\n */\nexport const trafficIncidentDetailsRequestSchema = commonServiceRequestSchema\n .extend({\n bbox: hasBBoxSchema.optional(),\n ids: z.array(z.string()).optional().describe('List of incident IDs'),\n trafficModelId: z.string().optional().describe('Traffic Model ID for temporal consistency'),\n categoryFilter: z\n .array(z.enum([...trafficIncidentCategories]))\n .optional()\n .describe('Incident category filter'),\n timeValidityFilter: z\n .array(z.enum(['present', 'future']))\n .optional()\n .describe('Time validity filter'),\n })\n .refine((data) => !(data.bbox && data.ids), {\n message: 'Provide either bbox or ids, not both',\n });\n","/**\n * @module services-customization\n * @group Customization\n */\n\nimport autocompleteCustomize from '../autocomplete-search/customize';\nimport evChargingStationsAvailabilityCustomize from '../ev-charging-stations-availability/customize';\nimport geocodeCustomize from '../geocode/customize';\nimport geometryDataCustomize from '../geometry-data/customize';\nimport geometrySearchCustomize from '../geometry-search/customize';\nimport placeByIdCustomize from '../place-by-id/customize';\nimport reachableRangeCustomize from '../reachable-range/customize';\nimport revgeoCustomize from '../revgeo/customize';\nimport routingCustomize from '../routing/customize';\nimport trafficIncidentDetailsCustomize from '../traffic-incident-details/customize';\n\n/**\n * Access to service implementation components for advanced customization.\n *\n * This object provides low-level access to the internal components of each service,\n * allowing developers to customize request building, response parsing, and other\n * aspects of service behavior. This is useful for advanced use cases like:\n * - Custom request/response transformations\n * - Integration with custom API gateways or proxies\n * - Adding custom validation or error handling\n * - Implementing request/response logging or monitoring\n * - Adapting to custom API endpoints or versions\n *\n * @remarks\n * Most developers won't need to use this directly. The standard service functions\n * (like `geocode`, `search`, `calculateRoute`) are sufficient for typical use cases.\n * Only use customization when you need to modify the internal service behavior.\n *\n * Each service exposes:\n * - Request builders: Functions that construct API requests\n * - Response parsers: Functions that transform API responses\n * - Templates: Configuration objects defining service behavior\n * - Validation schemas: Input parameter validation rules\n *\n * @example\n * ```typescript\n * // Access request builder for custom processing\n * import { customizeService } from '@tomtom-international/web-sdk-services';\n *\n * const { buildRequest } = customizeService.geocode;\n * const request = buildRequest({\n * key: 'your-api-key',\n * query: 'Amsterdam'\n * });\n *\n * // Access response parser for custom handling\n * const { parseResponse } = customizeService.geocode;\n * const rawApiResponse = await fetch(request.url);\n * const parsedData = parseResponse(await rawApiResponse.json());\n * ```\n *\n * @group Advanced\n */\nexport const customizeService: {\n reverseGeocode: typeof revgeoCustomize;\n geocode: typeof geocodeCustomize;\n geometryData: typeof geometryDataCustomize;\n geometrySearch: typeof geometrySearchCustomize;\n calculateRoute: typeof routingCustomize;\n reachableRange: typeof reachableRangeCustomize;\n evChargingStationsAvailability: typeof evChargingStationsAvailabilityCustomize;\n trafficIncidentDetails: typeof trafficIncidentDetailsCustomize;\n placeByID: typeof placeByIdCustomize;\n autocompleteSearch: typeof autocompleteCustomize;\n} = {\n reverseGeocode: revgeoCustomize,\n geocode: geocodeCustomize,\n geometryData: geometryDataCustomize,\n geometrySearch: geometrySearchCustomize,\n calculateRoute: routingCustomize,\n reachableRange: reachableRangeCustomize,\n evChargingStationsAvailability: evChargingStationsAvailabilityCustomize,\n trafficIncidentDetails: trafficIncidentDetailsCustomize,\n placeByID: placeByIdCustomize,\n autocompleteSearch: autocompleteCustomize,\n};\n","import { buildTrafficIncidentDetailsRequest } from './requestBuilder';\nimport { parseTrafficIncidentDetailsResponse } from './responseParser';\nimport type { TrafficIncidentDetailsTemplate } from './trafficIncidentDetailsTemplate';\nimport { trafficIncidentDetailsTemplate } from './trafficIncidentDetailsTemplate';\n\nconst customize: {\n buildTrafficIncidentDetailsRequest: typeof buildTrafficIncidentDetailsRequest;\n parseTrafficIncidentDetailsResponse: typeof parseTrafficIncidentDetailsResponse;\n trafficIncidentDetailsTemplate: TrafficIncidentDetailsTemplate;\n} = {\n buildTrafficIncidentDetailsRequest,\n parseTrafficIncidentDetailsResponse,\n trafficIncidentDetailsTemplate,\n};\nexport default customize;\n","import type {\n ChargingPark,\n ChargingParkWithAvailability,\n ChargingStationsAvailability,\n CommonPlaceProps,\n EVChargingStationWithAvailabilityPlaceProps,\n Place,\n Places,\n} from '@tomtom-org/maps-sdk/core';\nimport { bboxFromGeoJSON } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { EVChargingStationsAvailabilityTemplate } from './evChargingStationsAvailabilityTemplate';\nimport { evChargingStationsAvailabilityTemplate } from './evChargingStationsAvailabilityTemplate';\nimport type { ChargingStationsAvailabilityParams } from './types/evChargingStationsAvailabilityParams';\n\n/**\n * Get real-time availability of electric vehicle charging stations.\n *\n * Provides current operational status of charging points and connectors at EV charging parks,\n * enabling drivers to find available chargers before arriving at a location.\n *\n * @remarks\n * Key information returned:\n * - **Point-level status**: Available, Occupied, Reserved, Out of Service\n * - **Connector details**: Power ratings, plug types, current availability\n * - **Aggregated counts**: Quick overview of available vs occupied chargers\n * - **Access information**: Public, private, or restricted access\n * - **Opening hours**: When the charging facility is accessible\n *\n * @param params - Charging availability parameters with station ID\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to charging station availability information\n *\n * @example\n * ```typescript\n * // Get availability for a specific charging park\n * const availability = await evChargingStationsAvailability({\n * key: 'your-api-key',\n * id: 'charging-park-id-123'\n * });\n *\n * // Check how many chargers are available\n * const availableCount = availability.chargingPointAvailability.statusCounts.Available;\n * console.log(`${availableCount} chargers available`);\n *\n * // Find available CCS connectors\n * const ccsConnectors = availability.connectorAvailabilities.find(\n * ca => ca.connector.type === 'IEC62196Type2CCS'\n * );\n * ```\n *\n * @see [EV Charging Availability API](https://docs.tomtom.com/search-api/documentation)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [EV Charging Stations Availability Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/ev-charging-stations-availability)\n *\n * @group EV Charging\n */\nexport const evChargingStationsAvailability = async (\n params: ChargingStationsAvailabilityParams,\n customTemplate?: Partial<EVChargingStationsAvailabilityTemplate>,\n): Promise<ChargingStationsAvailability | undefined> =>\n callService(\n params,\n { ...evChargingStationsAvailabilityTemplate, ...customTemplate },\n 'EVChargingStationsAvailability',\n );\n\n/**\n * Enhance a place with real-time EV charging availability data.\n *\n * Fetches availability information for an EV charging station and merges it into\n * the place properties.\n *\n * @param place - The place to enhance with availability data\n *\n * @returns Promise resolving to the place with merged availability information\n * @returns undefined if no availability data is present for the `place` input parameter.\n *\n * @example\n * ```typescript\n * // After search, enhance place with availability\n * const searchResult = await search({ query: 'EV charging', ... });\n * const place = searchResult.features[0];\n *\n * const enhancedPlace = await getPlaceWithEVAvailability(place);\n * const availability = enhancedPlace.properties.chargingPark?.availability;\n *\n * if (availability) {\n * console.log('Available chargers:', availability.chargingPointAvailability.count);\n * }\n * ```\n *\n * @group EV Charging\n */\nexport const getPlaceWithEVAvailability = async <P extends CommonPlaceProps = CommonPlaceProps>(\n place: Place<P>,\n): Promise<Place<EVChargingStationWithAvailabilityPlaceProps> | undefined> => {\n const availabilityId = place.properties.dataSources?.chargingAvailability?.id;\n if (!availabilityId) {\n return undefined;\n }\n try {\n const availability = await evChargingStationsAvailability({ id: availabilityId });\n const poi = place.properties.poi;\n return availability\n ? {\n ...place,\n properties: {\n ...place.properties,\n // We override poi opening hours with the ones from the EV call, which might be better supported:\n ...(poi && { poi: { ...poi, openingHours: availability.openingHours } }),\n chargingPark: {\n ...(place.properties.chargingPark as ChargingPark),\n availability,\n },\n },\n }\n : undefined;\n } catch (e) {\n // (Likely a QPS limit error)\n console.error(e);\n return undefined;\n }\n};\n\n/**\n * Enhance multiple places with real-time EV charging availability data.\n *\n * Fetches availability information for all EV charging stations in a collection\n * and merges it into their properties. Non-EV places and EV stations without availability data are returned unchanged.\n *\n * @remarks\n * **Important**: Availability requests are made sequentially to avoid exceeding\n * API rate limits (QPS - Queries Per Second). For large result sets, this may\n * take some time.\n *\n * @param places - Collection of places to enhance\n * @param options - Configuration options\n *\n * @returns Promise resolving to places collection with merged availability\n *\n * @example\n * ```typescript\n * // Search for charging stations and add availability\n * const results = await search({\n * query: 'EV charging',\n * at: [4.9, 52.3],\n * radius: 5000\n * });\n *\n * const withAvailability = await getPlacesWithEVAvailability(results, {\n * excludeIfAvailabilityUnknown: true // Filter out stations with unknown availability\n * });\n *\n * // Display only stations with known availability\n * withAvailability.features.forEach(place => {\n * const available = place.properties.chargingPark?.availability?.chargingPointAvailability.count;\n * console.log(`${place.properties.poi?.name}: ${available} chargers`);\n * });\n * ```\n *\n * @group EV Charging\n */\nexport async function getPlacesWithEVAvailability<P extends CommonPlaceProps = CommonPlaceProps>(\n places: Places<P>,\n options?: {\n excludeIfAvailabilityUnknown: true;\n },\n): Promise<Places<EVChargingStationWithAvailabilityPlaceProps>>;\n\nexport async function getPlacesWithEVAvailability<P extends CommonPlaceProps = CommonPlaceProps>(\n places: Places<P>,\n options?: {\n /**\n * If true, places with unknown availability will be filtered out. Otherwise, they will be included.\n * @default false\n */\n excludeIfAvailabilityUnknown?: boolean;\n },\n): Promise<Places<P | EVChargingStationWithAvailabilityPlaceProps>> {\n const enhancedPlaces: Array<Place<P> | Place<EVChargingStationWithAvailabilityPlaceProps>> = [];\n for (const place of places.features) {\n // (We fetch the availabilities sequentially on purpose to prevent QPS limit errors)\n const placeWithAvailability = await getPlaceWithEVAvailability(place);\n if (placeWithAvailability) {\n enhancedPlaces.push(placeWithAvailability);\n } else if (!options?.excludeIfAvailabilityUnknown) {\n enhancedPlaces.push(place);\n }\n }\n return { ...places, features: enhancedPlaces, bbox: bboxFromGeoJSON(enhancedPlaces) };\n}\n\n/**\n * Type guard to check if a ChargingPark has availability data.\n *\n * @param chargingPark - The charging park to check\n * @returns True if the charging park has availability data\n *\n * @group EV Charging\n */\nexport const hasChargingAvailability = (\n chargingPark: ChargingPark | ChargingParkWithAvailability | undefined,\n): chargingPark is ChargingParkWithAvailability =>\n Boolean(chargingPark && 'availability' in chargingPark && chargingPark.availability);\n\nexport default evChargingStationsAvailability;\n","import type { Place } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { GeocodingTemplate } from './geocodingTemplate';\nimport { geocodingTemplate } from './geocodingTemplate';\nimport type { GeocodingParams } from './types/geocodingParams';\nimport type { GeocodingProps, GeocodingResponse } from './types/geocodingResponse';\n\n/**\n * Convert addresses into geographic coordinates (geocoding).\n *\n * The Geocode service translates addresses and place names into geographic coordinates,\n * enabling you to position markers on maps, calculate routes, or perform spatial analysis.\n *\n * @remarks\n * This service is optimized for address lookup and does not return POIs (Points of Interest).\n * For POI search, use the {@link search} function instead.\n *\n * Features:\n * - Highly tolerant of typos and incomplete addresses\n * - Handles various address formats and components\n * - Supports street addresses, intersections, and cross streets\n * - Works with higher-level geographies (cities, counties, states, countries)\n * - Returns structured address components\n *\n * @param params - Geocoding parameters including the address query\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to geocoded location results\n *\n * @example\n * ```typescript\n * // Geocode a complete address\n * const result = await geocode({\n * key: 'your-api-key',\n * query: '1600 Pennsylvania Avenue NW, Washington, DC'\n * });\n *\n * // Geocode with partial address\n * const partialResult = await geocode({\n * key: 'your-api-key',\n * query: 'Amsterdam, Netherlands'\n * });\n *\n * // Geocode with bias towards specific location\n * const biasedResult = await geocode({\n * key: 'your-api-key',\n * query: 'Main Street',\n * at: [4.9041, 52.3676], // Bias toward Amsterdam\n * limit: 5\n * });\n *\n * // Geocode an intersection\n * const intersection = await geocode({\n * key: 'your-api-key',\n * query: '5th Avenue & 42nd Street, New York'\n * });\n * ```\n *\n * @see [Geocode API Documentation](https://docs.tomtom.com/search-api/documentation/geocoding-service/geocode)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Geocoding Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/geocoding)\n *\n * @group Geocoding\n */\nexport const geocode = async (\n params: GeocodingParams,\n customTemplate?: Partial<GeocodingTemplate>,\n): Promise<GeocodingResponse> => callService(params, { ...geocodingTemplate, ...customTemplate }, 'Geocode');\n\n/**\n *\n * @param query\n * @group Geocoding\n */\nexport const geocodeOne = async (query: string): Promise<Place<GeocodingProps>> =>\n (await geocode({ query, limit: 1 })).features[0];\n","import type { CommonPlaceProps, Places, PolygonFeatures } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { GeometryDataTemplate } from './geometryDataTemplate';\nimport { geometryDataTemplate } from './geometryDataTemplate';\nimport type { GeometryDataParams, GeometryParams, GeometryPlaceParams } from './types/geometryDataParams';\n\n/**\n * Merge our internal Places \"properties\" response with Geometry data\n * @param places\n * @param geometries\n * @returns FeatureCollection<Polygon | MultiPolygon>,\n */\nconst mergePlacesWithGeometries = (places: Places, geometries: PolygonFeatures): PolygonFeatures<CommonPlaceProps> => {\n const placesIdMap = places.features.reduce(\n (acc, place) => {\n const geometryId = place.properties.dataSources?.geometry?.id;\n\n if (geometryId) {\n acc[geometryId] = {\n ...place.properties,\n placeCoordinates: place.geometry.coordinates,\n };\n }\n return acc;\n },\n {} as Record<string, unknown>,\n );\n\n const features = geometries.features.map((feature) => {\n if (feature.id && placesIdMap[feature.id]) {\n return { ...feature, properties: placesIdMap[feature.id] };\n }\n\n return feature;\n });\n\n return {\n type: 'FeatureCollection',\n bbox: geometries.bbox,\n features,\n } as PolygonFeatures<CommonPlaceProps>;\n};\n\n/**\n * Retrieve polygon geometries representing geographic area boundaries.\n *\n * The Geometry Data service returns coordinate sets that define the outlines of\n * geographic areas such as cities, countries, administrative regions, or POI footprints.\n * These polygons enable visualization of area boundaries, spatial analysis, and\n * geofencing applications.\n *\n * @remarks\n * Key features:\n * - **Batch requests**: Fetch up to 20 geometries in a single call\n * - **Multiple scales**: From countries down to building footprints\n * - **Place integration**: Can merge with place data for enriched results\n * - **Standard GeoJSON**: Returns standard Polygon/MultiPolygon features\n *\n * Common use cases:\n * - Display city or country boundaries on maps\n * - Show POI building footprints\n * - Create geofences for spatial queries\n * - Visualize administrative divisions\n * - Calculate areas and spatial relationships\n *\n * @param params - Geometry parameters with IDs or places to fetch boundaries for\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to polygon features representing area boundaries\n *\n * @example\n * ```typescript\n * // Fetch geometry by ID\n * const cityBoundary = await geometryData({\n * key: 'your-api-key',\n * geometries: ['geometry-id-123']\n * });\n *\n * // Fetch multiple geometries at once\n * const boundaries = await geometryData({\n * key: 'your-api-key',\n * geometries: ['country-id-1', 'city-id-2', 'poi-id-3']\n * });\n *\n * // Fetch and merge with place data\n * const searchResults = await search({ query: 'Amsterdam' });\n * const withBoundaries = await geometryData({\n * key: 'your-api-key',\n * geometries: searchResults // Places with geometry IDs\n * });\n * // Result includes both place properties and polygon boundaries\n * ```\n *\n * @see [Geometry Data API Documentation](https://docs.tomtom.com/search-api/documentation/additional-data-service/additional-data)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Geometry Data Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/geometry-data)\n *\n * @group Geometry\n */\nexport async function geometryData(\n params: GeometryDataParams,\n customTemplate?: Partial<GeometryDataTemplate>,\n): Promise<PolygonFeatures>;\nexport async function geometryData(\n params: GeometryPlaceParams,\n customTemplate?: Partial<GeometryDataTemplate>,\n): Promise<PolygonFeatures<CommonPlaceProps>>;\nexport async function geometryData(params: GeometryParams, customTemplate?: Partial<GeometryDataTemplate>) {\n const geometryResult = await callService(params, { ...geometryDataTemplate, ...customTemplate }, 'GeometryData');\n\n // If params.geometries is a FeatureCollection(Place), the properties will be merged with geometry results.\n if (!Array.isArray(params.geometries) && params.geometries.type === 'FeatureCollection') {\n return mergePlacesWithGeometries(params.geometries, geometryResult);\n }\n\n return geometryResult;\n}\n","import { callService } from '../shared/serviceTemplate';\nimport type { PlaceByIdTemplate } from './placeByIdTemplate';\nimport { placeByIdTemplate } from './placeByIdTemplate';\nimport type { PlaceByIdParams, PlaceByIdResponse } from './types';\n\n/**\n * Retrieve detailed information about a place using its unique identifier.\n *\n * The Place by ID service fetches comprehensive data for a specific place when you\n * have its ID from a previous search or from a place's dataSources. This is useful\n * for getting additional details or refreshing information about a known location.\n *\n * @remarks\n * Use cases:\n * - **Fetch POI details**: Get extended information like reviews, photos, amenities\n * - **Refresh place data**: Update information for a cached place\n * - **Deep linking**: Allow users to share/bookmark specific places\n * - **Related POI navigation**: Explore parent/child relationships\n *\n * The ID can be obtained from:\n * - Previous search results (place.id)\n * - POI details data source (place.properties.dataSources.poiDetails.id)\n * - Related POIs (place.properties.relatedPois[].id)\n * - Deep links or bookmarks\n *\n * @param params - Place by ID parameters with the place identifier\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to detailed place information\n *\n * @example\n * ```typescript\n * // Get place by ID from search result\n * const searchResult = await search({ query: 'Eiffel Tower' });\n * const placeId = searchResult.features[0].id;\n *\n * const placeDetails = await placeById({\n * key: 'your-api-key',\n * entityId: placeId\n * });\n *\n * // Get extended POI details\n * const place = searchResult.features[0];\n * const poiDetailsId = place.properties.dataSources?.poiDetails?.id;\n *\n * if (poiDetailsId) {\n * const detailedPOI = await placeById({\n * key: 'your-api-key',\n * entityId: poiDetailsId\n * });\n * // May include additional photos, reviews, extended hours, etc.\n * }\n *\n * // Navigate to related POI\n * const relatedPOI = place.properties.relatedPois?.[0];\n * if (relatedPOI) {\n * const parentPlace = await placeById({\n * key: 'your-api-key',\n * entityId: relatedPOI.id\n * });\n * console.log('Parent location:', parentPlace.properties.address);\n * }\n * ```\n *\n * @see [Place by ID API Documentation](https://docs.tomtom.com/search-api/documentation/place-by-id-service/place-by-id)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n *\n * @group Place\n */\nexport const placeById = async (\n params: PlaceByIdParams,\n customTemplate?: Partial<PlaceByIdTemplate>,\n): Promise<PlaceByIdResponse> => callService(params, { ...placeByIdTemplate, ...customTemplate }, 'PlaceById');\n\nexport default placeById;\n","import { bboxFromGeoJSON, PolygonFeature, PolygonFeatures } from '@tomtom-org/maps-sdk/core';\nimport { SDKServiceError } from '../shared/errors';\nimport { callService } from '../shared/serviceTemplate';\nimport type { ReachableRangeTemplate } from './reachableRangeTemplate';\nimport { reachableRangeTemplate } from './reachableRangeTemplate';\nimport type { ReachableRangeParams } from './types/reachableRangeParams';\n\n/**\n * Calculate the area reachable from a starting point within given constraints.\n *\n * The Reachable Range service (also known as isochrone) computes a polygon representing\n * all locations that can be reached from an origin within specified limits of time, distance,\n * or energy consumption. This is essential for range analysis, service area visualization,\n * and logistics planning.\n *\n * @remarks\n * Key features:\n * - **Time-based ranges**: Areas reachable within a time budget (e.g., 30 minutes)\n * - **Distance-based ranges**: Areas within a distance limit (e.g., 50km)\n * - **Energy-based ranges**: EV range considering battery consumption\n * - **Traffic awareness**: Accounts for current and historic traffic patterns\n * - **Vehicle-specific**: Considers vehicle characteristics and constraints\n *\n * Common use cases:\n * - **Service area mapping**: \"Show areas we can deliver to within 1 hour\"\n * - **EV range visualization**: Display drivable range on current battery\n * - **Real estate**: \"Find homes within 45 minutes of workplace\"\n * - **Emergency services**: Calculate ambulance/fire truck response areas\n * - **Market analysis**: Identify customer catchment areas\n * - **Location planning**: Optimize facility placement based on coverage\n *\n * @param params Reachable range parameters including origin and budget constraints\n * @param customTemplate Advanced customization for request/response handling\n *\n * @returns Promise resolving to a polygon representing the reachable area\n *\n * @example\n * ```typescript\n * // Calculate 30-minute drive time range\n * const range30min = await calculateReachableRange({\n * key: 'your-api-key',\n * origin: [4.9041, 52.3676], // Amsterdam\n * timeBudgetInSec: 1800 // 30 minutes\n * });\n *\n * // Calculate 50km distance range\n * const range50km = await calculateReachableRange({\n * key: 'your-api-key',\n * origin: [4.9041, 52.3676],\n * distanceBudgetInMeters: 50000\n * });\n *\n * // EV range based on battery\n * const evRange = await calculateReachableRange({\n * key: 'your-api-key',\n * origin: [4.9041, 52.3676],\n * fuelBudgetInkWh: 20, // Remaining battery\n * vehicleEngineType: 'electric',\n * constantSpeedConsumptionInkWhPerHundredkm: [[50, 8], [80, 12]]\n * });\n *\n * // Traffic-aware range at departure time\n * const morningRange = await calculateReachableRange({\n * key: 'your-api-key',\n * origin: [4.9041, 52.3676],\n * timeBudgetInSec: 2700, // 45 minutes\n * departAt: new Date('2025-10-20T08:00:00Z') // Rush hour\n * });\n * ```\n *\n * @see [Reachable Range API Documentation](https://docs.tomtom.com/routing-api/documentation/routing/calculate-reachable-range)\n * @see [Routing Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/routing/quickstart)\n *\n * @group Routing\n */\nexport const calculateReachableRange = async (\n params: ReachableRangeParams,\n customTemplate?: Partial<ReachableRangeTemplate>,\n): Promise<PolygonFeature<ReachableRangeParams>> =>\n callService(params, { ...reachableRangeTemplate, ...customTemplate }, 'Reachable Range');\n\n/**\n * Calculate multiple reachable range areas from different origins or with different constraints.\n *\n * Computes several isochrone polygons in sequence, useful for comparing ranges from multiple\n * locations, visualizing multiple time/distance rings from the same origin, or analyzing\n * different vehicle scenarios.\n *\n * @remarks\n * Use cases:\n * - **Multi-location comparison**: Compare service areas of different store locations\n * - **Concentric ranges**: Create 15/30/45 minute drive time rings from one origin\n * - **Scenario analysis**: Compare ranges for different vehicle types or times of day\n * - **Coverage optimization**: Find optimal facility locations with minimal overlap\n *\n * Note: Ranges are calculated sequentially to avoid rate limiting. For large batches,\n * consider implementing your own parallel processing with appropriate throttling.\n *\n * @param paramsArray Array of reachable range parameters, one for each area to calculate\n * @param options.signal An `AbortSignal` to cancel in-flight requests between iterations.\n * @param customTemplate Advanced customization for request/response handling\n *\n * @returns Promise resolving to a FeatureCollection of reachable area polygons\n *\n * @example\n * ```typescript\n * // Calculate concentric drive time rings (15, 30, 45 minutes)\n * const timeRings = await calculateReachableRanges([\n * { key: 'your-api-key', origin: [4.9, 52.3], timeBudgetInSec: 900 },\n * { key: 'your-api-key', origin: [4.9, 52.3], timeBudgetInSec: 1800 },\n * { key: 'your-api-key', origin: [4.9, 52.3], timeBudgetInSec: 2700 }\n * ]);\n *\n * // Compare service areas of multiple stores\n * const storeRanges = await calculateReachableRanges([\n * { key: 'your-api-key', origin: [4.9, 52.3], timeBudgetInSec: 1800 },\n * { key: 'your-api-key', origin: [4.5, 51.9], timeBudgetInSec: 1800 },\n * { key: 'your-api-key', origin: [5.1, 52.1], timeBudgetInSec: 1800 }\n * ]);\n *\n * // Compare EV ranges at different battery levels\n * const batteryRanges = await calculateReachableRanges([\n * {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * fuelBudgetInkWh: 10,\n * vehicleEngineType: 'electric'\n * },\n * {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * fuelBudgetInkWh: 20,\n * vehicleEngineType: 'electric'\n * }\n * ]);\n * ```\n *\n * @see [Reachable Range API Documentation](https://docs.tomtom.com/routing-api/documentation/routing/calculate-reachable-range)\n * @see [Routing Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/routing/quickstart)\n *\n * @group Routing\n */\nexport const calculateReachableRanges = async (\n paramsArray: ReachableRangeParams[],\n options?: { signal?: AbortSignal },\n customTemplate?: Partial<ReachableRangeTemplate>,\n): Promise<PolygonFeatures<ReachableRangeParams>> => {\n const features: PolygonFeature<ReachableRangeParams>[] = [];\n for (const params of paramsArray) {\n // Throws AbortError if a newer call has cancelled this one before the next request starts\n options?.signal?.throwIfAborted();\n try {\n // we sequentially fetch reachable ranges (less speed but better to prevent QPS limit breaches):\n features.push(await calculateReachableRange(params, customTemplate));\n } catch (error) {\n // Re-throw non-API errors (e.g. validation/programming errors) and critical HTTP errors\n // (403 Forbidden, 429 Too Many Requests) — only silently skip API errors that indicate\n // no reachable range could be computed at this location (e.g. no road network).\n if (!(error instanceof SDKServiceError) || error.status === 403 || error.status === 429) {\n throw error;\n }\n }\n }\n const bbox = bboxFromGeoJSON(features);\n return { type: 'FeatureCollection', ...(bbox && { bbox }), features };\n};\n","import type { Place, RevGeoAddressProps } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { ReverseGeocodingTemplate } from './reverseGeocodingTemplate';\nimport { reverseGeocodingTemplate } from './reverseGeocodingTemplate';\nimport type { ReverseGeocodingParams } from './types/reverseGeocodingParams';\n\n/**\n * Response from the reverse geocoding service.\n *\n * Contains a place with address information for the given coordinates.\n *\n * @group Reverse Geocoding\n */\nexport type ReverseGeocodingResponse = Place<RevGeoAddressProps>;\n\n/**\n * Convert geographic coordinates into human-readable addresses (reverse geocoding).\n *\n * Reverse geocoding translates latitude/longitude coordinates into street addresses,\n * which is essential for location-based applications that need to display addresses\n * from GPS coordinates or map clicks.\n *\n * @remarks\n * Common use cases:\n * - **Tracking applications**: Convert GPS coordinates from devices into addresses\n * - **Map interactions**: Display address when user clicks on map\n * - **Location sharing**: Show readable location instead of coordinates\n * - **Delivery apps**: Confirm pickup/dropoff addresses from driver location\n * - **Asset tracking**: Display current location of vehicles or equipment\n *\n * Features:\n * - Returns complete address hierarchy (street, city, state, country)\n * - Supports cross-street results\n * - Includes side of street information\n * - Provides address ranges for streets\n * - Returns multiple result types (street, POI, geography)\n *\n * @param params - Reverse geocoding parameters including coordinates\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to the address for the given coordinates\n *\n * @example\n * ```typescript\n * // Get address for coordinates\n * const address = await reverseGeocode({\n * key: 'your-api-key',\n * position: [4.9041, 52.3676] // Amsterdam coordinates\n * });\n * // Returns: Dam, 1012 Amsterdam, Netherlands\n *\n * // Get address with specific street number\n * const specificAddress = await reverseGeocode({\n * key: 'your-api-key',\n * position: [-77.0369, 38.8977], // Washington DC\n * number: '1600'\n * });\n * // Returns: 1600 Pennsylvania Avenue NW\n *\n * // Get nearest cross street\n * const crossStreet = await reverseGeocode({\n * key: 'your-api-key',\n * position: [-74.0060, 40.7128], // New York\n * returnRoadUse: true\n * });\n * ```\n *\n * @see [Reverse Geocode API Documentation](https://docs.tomtom.com/search-api/documentation/reverse-geocoding-service/reverse-geocode)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Reverse Geocoding Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/reverse-geocoding)\n *\n * @group Reverse Geocoding\n */\nexport const reverseGeocode = async (\n params: ReverseGeocodingParams,\n customTemplate?: Partial<ReverseGeocodingTemplate>,\n): Promise<ReverseGeocodingResponse> =>\n callService(params, { ...reverseGeocodingTemplate, ...customTemplate }, 'ReverseGeocode');\n\nexport default reverseGeocode;\n","import type { Routes } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { CalculateRouteTemplate } from './calculateRouteTemplate';\nimport { calculateRouteTemplate } from './calculateRouteTemplate';\nimport type { CalculateRouteParams } from './types/calculateRouteParams';\n\n/**\n * Calculates a route between an origin and destination, optionally passing through extra waypoints.\n *\n * @param params - Route calculation parameters including locations, travel mode, and other options\n * @param customTemplate - Optional template customization for request/response handling\n * @returns Promise resolving to calculated route(s) with geometry, distance, and travel time\n *\n * @see [Calculate Route API Documentation](https://docs.tomtom.com/routing-api/documentation/tomtom-maps/calculate-route)\n *\n * @group Routing\n */\nexport const calculateRoute = async (\n params: CalculateRouteParams,\n customTemplate?: Partial<CalculateRouteTemplate>,\n): Promise<Routes> => callService(params, { ...calculateRouteTemplate, ...customTemplate }, 'Routing');\n","import { z } from 'zod';\nimport { commonSearchParamsSchema } from '../search/commonSearchParamsSchema';\nimport { commonGeocodeAndFuzzySearchParamsSchema } from '../shared/schema/commonGeocodeAndFuzzySearchParamsSchema';\n\nconst fuzzySearchRequestOptional = z.object({\n minFuzzyLevel: z\n .number()\n .min(1)\n .max(4)\n .optional()\n .describe('Minimum fuzzy matching level (1-4, higher allows more typos)'),\n maxFuzzyLevel: z\n .number()\n .min(1)\n .max(4)\n .optional()\n .describe('Maximum fuzzy matching level (1-4, higher allows more typos)'),\n});\n\n/**\n * @ignore\n */\nexport const fuzzySearchRequestSchema = commonSearchParamsSchema.extend(\n commonGeocodeAndFuzzySearchParamsSchema.extend(fuzzySearchRequestOptional.shape).shape,\n);\n","import { bboxFromGeoJSON, bboxOnlyIfWithArea } from '@tomtom-org/maps-sdk/core';\nimport { latLonAPIToPosition } from '../shared/geometry';\nimport { parseSearchAPIResult, parseSummaryAPI } from '../shared/searchResultParsing';\nimport type { FuzzySearchResponse, FuzzySearchResponseAPI, QueryIntent, QueryIntentAPI } from './types';\n\nconst queryIntentApiToSdk = (intentApi: QueryIntentAPI): QueryIntent => {\n let intent;\n switch (intentApi.type) {\n case 'COORDINATE':\n intent = { ...intentApi, details: { position: latLonAPIToPosition(intentApi.details) } };\n break;\n case 'NEARBY':\n intent = {\n ...intentApi,\n details: {\n position: latLonAPIToPosition({ lon: intentApi.details.lon, lat: intentApi.details.lat }),\n text: intentApi.details.text,\n query: intentApi.details.query,\n },\n };\n break;\n case 'BOOKMARK':\n case 'W3W':\n intent = intentApi;\n }\n return intent;\n};\n\n/**\n * Default function to parse a fuzzy search response.\n * @param apiResponse The API response.\n */\nexport const parseFuzzySearchResponse = (apiResponse: FuzzySearchResponseAPI): FuzzySearchResponse => {\n const features = apiResponse.results.map(parseSearchAPIResult);\n const bbox = bboxOnlyIfWithArea(bboxFromGeoJSON(features));\n return {\n type: 'FeatureCollection',\n properties: {\n ...parseSummaryAPI(apiResponse.summary),\n queryIntent: apiResponse.summary.queryIntent.map(queryIntentApiToSdk),\n },\n features,\n ...(bbox && { bbox }),\n };\n};\n","import type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { fuzzySearchRequestSchema } from './fuzzySearchRequestSchema';\nimport { buildFuzzySearchRequest } from './requestBuilder';\nimport { parseFuzzySearchResponse } from './responseParser';\nimport type { FuzzySearchParams, FuzzySearchResponse, FuzzySearchResponseAPI } from './types';\n\n/**\n * Fuzzy search service template type.\n * @ignore\n */\nexport type FuzzySearchTemplate = ServiceTemplate<FuzzySearchParams, URL, FuzzySearchResponseAPI, FuzzySearchResponse>;\n\n/**\n * Fuzzy search service template main implementation.\n * @ignore\n */\nexport const fuzzySearchTemplate: FuzzySearchTemplate = {\n requestValidation: { schema: fuzzySearchRequestSchema },\n buildRequest: buildFuzzySearchRequest,\n sendRequest: get,\n parseResponse: parseFuzzySearchResponse,\n};\n","import { bboxFromGeoJSON } from '@tomtom-org/maps-sdk/core';\nimport { arrayToCSV } from '../shared/arrays';\nimport { appendCommonSearchParams, PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport { appendByJoiningParamValue, appendOptionalParam } from '../shared/request/requestBuildingUtils';\nimport type { FuzzySearchParams } from './types';\n\nconst buildUrlBasePath = (mergedOptions: FuzzySearchParams): string =>\n mergedOptions.customServiceBaseURL ??\n `${mergedOptions.commonBaseURL}${PLACES_URL_PATH}/search/${mergedOptions.query}.json`;\n\n/**\n * Default function for building a fuzzy search request from {@link FuzzySearchParams}\n * @param params The fuzzy search parameters, with global configuration already merged into them.\n */\nexport const buildFuzzySearchRequest = (params: FuzzySearchParams): URL => {\n const url = new URL(`${buildUrlBasePath(params)}`);\n appendCommonSearchParams(url, params);\n const urlParams = url.searchParams;\n appendOptionalParam(urlParams, 'typeahead', params.typeahead);\n appendOptionalParam(urlParams, 'ofs', params.offset);\n appendByJoiningParamValue(urlParams, 'countrySet', params.countries);\n appendOptionalParam(urlParams, 'radius', params.radiusMeters);\n const bbox = params.boundingBox && bboxFromGeoJSON(params.boundingBox);\n if (bbox) {\n urlParams.append('topLeft', arrayToCSV([bbox[3], bbox[0]]));\n urlParams.append('btmRight', arrayToCSV([bbox[1], bbox[2]]));\n }\n appendOptionalParam(urlParams, 'minFuzzyLevel', params.minFuzzyLevel);\n appendOptionalParam(urlParams, 'maxFuzzyLevel', params.maxFuzzyLevel);\n return url;\n};\n","import type { Place, Places, SearchPlaceProps } from '@tomtom-org/maps-sdk/core';\nimport type { FuzzySearchParams, QueryIntent } from '../fuzzy-search';\nimport { fuzzySearch } from '../fuzzy-search/fuzzySearch';\nimport type { FuzzySearchTemplate } from '../fuzzy-search/fuzzySearchTemplate';\nimport type { GeometrySearchParams } from '../geometry-search';\nimport { geometrySearch } from '../geometry-search/geometrySearch';\nimport type { GeometrySearchTemplate } from '../geometry-search/geometrySearchTemplate';\nimport type { SearchSummary } from '../shared';\n\ntype SearchFeatureCollectionProps = SearchSummary & {\n queryIntent?: QueryIntent[];\n};\n\n/**\n * Search service response containing places that match the query.\n *\n * Collection of place features with search-specific properties like relevance scores and distances.\n *\n * @group Search\n */\nexport type SearchResponse = Places<SearchPlaceProps, SearchFeatureCollectionProps>;\n\n/**\n * Universal search function for finding places by text query or within geometries.\n *\n * This is a unified interface that automatically routes to either:\n * - **Geometry Search**: When geometries parameter is provided (search within specific areas)\n * - **Fuzzy Search**: When no geometries provided (free-text search)\n *\n * @remarks\n * The search service provides:\n * - POI (Points of Interest) search\n * - Address search\n * - Geographic area search\n * - Category-based filtering\n * - Position-based relevance ranking\n *\n * Results are ranked by relevance with scores and optional distances.\n *\n * @param params - Search parameters (either GeometrySearchParams or FuzzySearchParams)\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to a collection of matching places\n *\n * @example\n * ```typescript\n * // Free-text search near a location\n * const results = await search({\n * key: 'your-api-key',\n * query: 'pizza restaurant',\n * at: [4.9041, 52.3676], // Amsterdam\n * limit: 10\n * });\n *\n * // Search within a specific area\n * const areaResults = await search({\n * key: 'your-api-key',\n * query: 'coffee shop',\n * geometries: [polygon], // Search within this polygon\n * limit: 20\n * });\n *\n * // Category search\n * const restaurants = await search({\n * key: 'your-api-key',\n * query: 'restaurant',\n * categorySet: [7315], // Restaurant category\n * at: [4.9041, 52.3676],\n * radius: 5000 // Within 5km\n * });\n * ```\n *\n * @see [Search API Documentation](https://docs.tomtom.com/search-api/documentation/search-service/search-service)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Search Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/search)\n *\n * @group Search\n */\nexport const search = async (\n params: GeometrySearchParams | FuzzySearchParams,\n customTemplate?: Partial<GeometrySearchTemplate | FuzzySearchTemplate>,\n): Promise<SearchResponse> =>\n 'geometries' in params\n ? geometrySearch(params, customTemplate as GeometrySearchTemplate)\n : fuzzySearch(params, customTemplate as FuzzySearchTemplate);\n\n/**\n * Search for a single place by text query.\n *\n * Convenience function that calls {@link search} and returns the first result.\n *\n * @param query - Search query string\n * @returns Promise resolving to the first matching place, or undefined if no results\n *\n * @example\n * ```typescript\n * const place = await searchOne('Vondelpark Amsterdam');\n * if (place) {\n * console.log(place.properties.name);\n * }\n * ```\n *\n * @remarks\n * * Useful to quickly find a single place, particularly a POI.\n * * If you want to find a single address, consider 'geocodeOne'.\n *\n * @group Search\n */\nexport const searchOne = async (query: string): Promise<Place<SearchPlaceProps> | undefined> =>\n (await search({ query, limit: 1 })).features[0];\n","import { callService } from '../shared/serviceTemplate';\nimport type { FuzzySearchTemplate } from './fuzzySearchTemplate';\nimport { fuzzySearchTemplate } from './fuzzySearchTemplate';\nimport type { FuzzySearchParams, FuzzySearchResponse } from './types';\n\n/**\n * Search for places using free-text queries with fuzzy matching.\n *\n * The Fuzzy Search service provides a flexible search that handles typos, abbreviations,\n * and incomplete addresses. It searches across POIs (Points of Interest), addresses,\n * and geographic areas to find the best matches for your query.\n *\n * @remarks\n * Key features:\n * - **Typo tolerance**: Handles misspellings and typing errors\n * - **Partial matching**: Works with incomplete queries\n * - **Multi-category search**: Searches POIs, addresses, and places simultaneously\n * - **Position bias**: Prioritizes results near a given location\n * - **Flexible input**: Accepts natural language queries\n *\n * The service is ideal for:\n * - User-facing search boxes where typos are common\n * - Location lookup without knowing exact names\n * - General \"find anything\" search functionality\n * - Autocomplete with final selection\n *\n * @param params Fuzzy search parameters including the search query\n * @param customTemplate Advanced customization for request/response handling\n *\n * @returns Promise resolving to a collection of matching places\n *\n * @example\n * ```typescript\n * // Basic search with typo tolerance\n * const results = await fuzzySearch({\n * key: 'your-api-key',\n * query: 'amstrdam' // Typo: missing 'e'\n * });\n * // Still finds \"Amsterdam\"\n *\n * // Search near a specific location\n * const nearby = await fuzzySearch({\n * key: 'your-api-key',\n * query: 'pizza',\n * at: [4.9041, 52.3676], // Amsterdam\n * radius: 2000, // Within 2km\n * limit: 10\n * });\n *\n * // Search with category filter\n * const restaurants = await fuzzySearch({\n * key: 'your-api-key',\n * query: 'italian',\n * categorySet: [7315], // Restaurant category\n * at: [4.9041, 52.3676]\n * });\n *\n * // Partial address search\n * const addresses = await fuzzySearch({\n * key: 'your-api-key',\n * query: '123 main st',\n * countrySet: ['US'],\n * limit: 5\n * });\n * ```\n *\n * @see [Fuzzy Search API Documentation](https://docs.tomtom.com/search-api/documentation/search-service/fuzzy-search)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Search Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/search)\n *\n * @ignore (exposed via 'search')\n */\nexport const fuzzySearch = async (\n params: FuzzySearchParams,\n customTemplate?: Partial<FuzzySearchTemplate>,\n): Promise<FuzzySearchResponse> => callService(params, { ...fuzzySearchTemplate, ...customTemplate }, 'FuzzySearch');\n\nexport default fuzzySearch;\n","import type { TrafficIncidentDetails } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { TrafficIncidentDetailsTemplate } from './trafficIncidentDetailsTemplate';\nimport { trafficIncidentDetailsTemplate } from './trafficIncidentDetailsTemplate';\nimport type { TrafficIncidentDetailsParams } from './types/trafficIncidentDetailsParams';\n\n/**\n * Fetch detailed information about traffic incidents.\n *\n * Query incidents either by a geographic bounding box or by a list of incident IDs.\n * Results are GeoJSON Features whose geometry is a `Point` (localised incidents) or\n * a `LineString` (incidents spanning a stretch of road).\n *\n * @remarks\n * **Two query modes:**\n *\n * - **Bounding box** (`bbox`): Returns all incidents within the given area.\n * Maximum area is 10,000 km².\n * - **By IDs** (`ids`): Returns the specified incidents directly.\n * GET is used automatically for up to 5 IDs; POST for up to 100 IDs.\n *\n * **Key data provided per incident:**\n * - Category (`iconCategory`): type of incident (accident, roadworks, jam, etc.)\n * - Delay magnitude: severity of the delay (`minor`, `moderate`, `major`, …)\n * - Geometry: exact location or extent of the incident on the road network\n * - Time information: start/end times and whether the incident is `present` or `future`\n * - Events: one or more detailed event descriptions\n *\n * @param params - Traffic Incident Details parameters (bbox or ids)\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to a {@link TrafficIncidentDetails} object containing the matching incidents\n *\n * @example\n * ```typescript\n * // Query by bounding box (Amsterdam area)\n * const result = await trafficIncidentDetails({\n * bbox: [4.728, 52.278, 5.080, 52.479]\n * });\n *\n * result.incidents.forEach(incident => {\n * console.log(incident.properties.iconCategory); // 'accident' | 'jam' | …\n * console.log(incident.properties.magnitudeOfDelay); // 'minor' | 'major' | …\n * console.log(incident.geometry); // Point or LineString\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Query up to 5 specific incidents by ID (GET)\n * const result = await trafficIncidentDetails({\n * ids: ['incident-id-1', 'incident-id-2']\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Query many incident IDs — POST is used automatically when ids.length > 5\n * const result = await trafficIncidentDetails({\n * ids: largeIdArray\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Filter by category and include future incidents\n * const result = await trafficIncidentDetails({\n * bbox: [4.728, 52.278, 5.080, 52.479],\n * categoryFilter: ['accident', 'road-closed'],\n * timeValidityFilter: ['present', 'future']\n * });\n * ```\n *\n * @see [Incident Details API Documentation](https://docs.tomtom.com/traffic-api/documentation/tomtom-orbis-maps/traffic-incidents/incident-details)\n * @see [Incident Details Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/traffic/incident-details)\n *\n * @group Traffic\n */\nexport const trafficIncidentDetails = async (\n params: TrafficIncidentDetailsParams,\n customTemplate?: Partial<TrafficIncidentDetailsTemplate>,\n): Promise<TrafficIncidentDetails> =>\n callService(params, { ...trafficIncidentDetailsTemplate, ...customTemplate }, 'TrafficIncidentDetails');\n"],"names":["APICode","SDKError","Error","constructor","message","service","issues","super","this","captureStackTrace","APIErrorCode","TOO_MANY_REQUESTS","FORBIDDEN","SDKServiceError","status","parseDefaultResponseError","error","serviceName","data","errorText","buildResponseError","parseResponseError","fetchError","buildValidationError","commonServiceRequestSchema","z","object","apiKey","string","optional","describe","commonBaseURL","customServiceBaseURL","language","ValidationError","zodError","map","issue","path","length","join","callService","async","params","template","customApiVersion","getAPIVersion","mergedParams","mergeFromGlobal","apiVersion","validateRequest","config","validation","schema","extend","shape","superRefine","ctx","addIssue","code","refinements","refinement","check","safeParse","success","validateRequestSchema","requestValidation","e","Promise","reject","apiRequest","buildRequest","headers","generateTomTomHeaders","onAPIRequest","apiResponse","sendRequest","onAPIResponse","parseResponse","FetchError","name","returnOrThrow","response","ok","json","errorBody","contentType","get","bodyUsed","statusText","includes","detailedError","text","url","fetch","post","input","method","body","JSON","stringify","fetchWith","lineStringCoordsSchema","array","number","geometrySchema","type","enum","coordinates","union","radius","radiusMeters","bbox","refine","Boolean","featureSchema","literal","geometry","id","properties","any","featureCollectionSchema","features","hasLngLatSchema","tuple","min","max","geoJsonbBoxSchema","arr","geoJSONObjectSchema","hasBBoxSchema","autocompleteSearchRequestMandatory","query","autocompleteSearchRequestOptional","position","limit","countries","resultType","autocompleteSearchRequestSchema","appendCommonParams","urlParams","append","String","appendByRepeatingParamName","paramName","paramArray","param","appendByJoiningParamValue","values","Array","isArray","appendOptionalParam","value","isNil","appendLatLonParamsFromPosition","hasLngLat","getPosition","PLACES_URL_PATH","appendCommonSearchParams","searchUrl","searchParams","fuelTypes","indexes","poiBrands","poiCategories","poiCategory","poiCategoriesToID","connectors","mapcodes","extendedPostalCodesFor","minPowerKW","maxPowerKW","view","openingHours","timeZone","relatedPois","geographyTypes","buildAutocompleteSearchRequest","URL","mergedOptions","csvLatLngToPosition","csv","splitLatLng","split","Number","positionToCSVLatLon","apiToGeoJSONBBox","apiBBox","westSouth","eastNorth","topLeftPoint","lon","btmRightPoint","lat","southWest","northEast","latLonAPIToPosition","point","parseAutocompleteSearchResponse","geoBias","context","autocompleteSearchTemplate","autocompleteSearch","customTemplate","customize","evChargingStationsAvailabilityRequestSchema","buildEVChargingStationsAvailabilityRequest","buildUrlBasePath","toChargingSpeed","powerInKW","toChargingPointAvailability","chargingStations","availability","count","statusCounts","station","chargingPoint","chargingPoints","areEqual","connectorA","connectorB","ratedPowerKW","addConnectorCountAndStatus","availabilities","connector","existingAvailability","find","connectorAvailability","push","toConnectorCounts","counts","existingCount","connectorCount","addConnectorCount","toConnectorBasedAvailabilities","parseMoment","momentApi","year","month","day","dateYyyymmdd","splitDate","parseInt","parseYyyymmddDate","date","dateYYYYMMDD","hour","minute","Date","alwaysOpenInThisPeriod","timeRanges","start","end","parseOpeningHours","openingHoursApi","timeRangeApi","startTime","endTime","mode","alwaysOpenThisPeriod","parseSearchAPIResult","result","entryPoints","poi","dist","boundingBox","chargingPark","rest","omit","connectorType","chargingSpeed","toPointGeometry","distance","entrypoint","brands","brand","categoryIds","categorySet","category","parseSummaryAPI","summary","parseEVChargingStationsAvailabilityResponse","results","accessType","stations","chargingPointAvailability","connectorAvailabilities","evChargingStationsAvailabilityTemplate","apiError","errorMessage","commonGeocodeAndFuzzySearchParamsSchema","typeahead","boolean","offset","placesParamsMandatory","placesParamsOptional","views","commonPlacesParamsSchema","geocodingRequestSchema","arrayToCSV","sampleWithinMaxLength","maxLength","sampledArray","i","increment","Math","ceil","buildGeocodingRequest","bboxFromGeoJSON","parseApiResult","addressRanges","entityType","geographyType","from","to","parseGeocodingResponse","bboxOnlyIfWithArea","geocodingTemplate","geometryDataRequestMandatory","geometries","geometryDataRequestOptional","zoom","geometryDataRequestSchema","getGeometryIDs","placesArray","place","dataSources","filter","buildGeometryDataRequest","geometryIDs","appendGeometries","parseGeometryDataResponse","additionalData","flatMap","geometryData","feature","generateId","geometryDataTemplate","poiCategoriesToIdZodObject","searchExtraParamsOptional","keyof","minFuzzyLevel","mixFuzzyLevel","commonSearchParamsSchema","geometrySearchRequestMandatory","geometrySearchRequestSchema","sdkGeometryToApiGeometries","searchGeometry","vertices","coord","polygonSizeMap","Map","forEach","polygon","bboxOfPolygon","bboxFromCoordsArray","polygonSize","abs","set","entries","sort","a","b","splice","keys","findFiftyLargestPolygons","polygonCoords","buildGeometrySearchRequest","geometryList","parseGeometrySearchResponse","geometrySearchTemplate","geometrySearch","placeByIdRequestMandatory","entityId","placeByIdRequestOptional","placeByIdRequestSchema","buildPlaceByIdRequest","parsePlaceByIdResponse","placeByIdTemplate","parseRoutingResponseError","description","positiveNumber","positive","nonNegativeNumber","percentageNumber","optionalPositiveNumber","optionalNonNegativeNumber","optionalNormalizedNumber","speedToConsumptionRateSchema","speedKMH","consumptionUnitsPer100KM","baseConsumptionModelSchema","efficiency","acceleration","deceleration","uphill","downhill","speedConsumptionArray","combustionConsumptionModelSchema","speedsToConsumptionsLiters","auxiliaryPowerInLitersPerHour","fuelEnergyDensityInMJoulesPerLiter","electricConsumptionModelSchema","speedsToConsumptionsKWH","auxiliaryPowerInkW","consumptionInKWHPerKMAltitudeGain","recuperationInKWHPerKMAltitudeLoss","chargingConnectorSchema","currentType","currentTypes","plugTypes","baseLoadInkW","maxPowerInkW","maxVoltageInV","maxCurrentInA","voltageRange","minVoltageInV","batteryCurveSchema","stateOfChargeInkWh","chargingModelSchema","maxChargeKWH","batteryCurve","chargingConnectors","chargingTimeOffsetInSec","combustionEngineModelSchema","consumption","electricEngineModelSchema","charging","vehicleDimensionsSchema","lengthMeters","widthMeters","heightMeters","weightKG","axleWeightKG","predefinedVehicleModelSchema","variantId","explicitVehicleModelSchema","dimensions","engine","vehicleModelSchema","genericVehicleStateSchema","heading","combustionVehicleStateSchema","currentFuelInLiters","electricVehicleStateByPercentageSchema","currentChargePCT","electricVehicleStateByKwhSchema","currentChargeInkWh","electricVehicleStateSchema","chargingPreferencesPCTSchema","minChargeAtDestinationPCT","minChargeAtChargingStopsPCT","chargingPreferencesKWHSchema","minChargeAtDestinationInkWh","minChargeAtChargingStopsInkWh","chargingPreferencesSchema","electricVehiclePreferencesSchema","chargingPreferences","baseVehicleParamsSchema","model","restrictions","loadTypes","maxSpeedKMH","adrCode","commercial","genericVehicleParamsSchema","engineType","undefined","state","preferences","combustionVehicleParamsSchema","electricVehicleParamsSchema","vehicleParametersSchema","discriminatedUnion","commonRoutingRequestSchema","costModel","avoid","avoidableTypes","traffic","routeType","thrillingParams","hilliness","windingness","travelMode","vehicle","when","option","budgetTypes","reachableRangeRequestSchemaMandatory","origin","budget","reachableRangeRequestSchemaOptional","maxFerryLengthMeters","smoothing","reachableRangeRequestSchema","buildSpeedToConsumptionString","speedsToConsumptions","speedToConsumption","appendVehicleEngineModel","appendConsumptionEfficiency","appendElectricConsumptionModel","chargingModel","appendChargingModel","consumptionModel","appendCombustionEngine","appendVehicleModel","vehicleParams","appendVehicleDimensions","appendVehicleParams","combustionState","electricState","kwhElectricState","pctElectricState","appendVehicleState","chargingPrefs","kwhChargingPrefs","pctChargingPrefs","appendVehiclePreferences","appendVehicleRestrictions","appendCommonRoutingParams","formattedDate","toISOString","appendWhenParams","getMaxChargeKWH","appendBudget","toString","currentChargeKWH","pctState","getCurrentChargeKWH","remainingKWH","buildPostData","getPositionStrict","buildReachableRangeRequest","delete","parseReachableRangeResponse","reachableRange","boundary","longitude","latitude","reachableRangeTemplate","buildRevGeoRequest","lngLat","allowFreeformNewline","returnSpeedLimit","returnRoadUse","roadUses","parseRevGeoResponse","firstApiResult","addresses","sideOfStreet","offsetPosition","address","streetNumber","originalPosition","revGeocodeRequestMandatory","revGeocodeRequestOptional","returnMatchType","reverseGeocodingTemplate","waypointLikeSchema","pathLikeSchema","mandatorySchema","locations","optionalSchema","computeAdditionalTravelTimeFor","vehicleHeading","maxAlternatives","sectionTypes","inputSectionTypesWithGuidance","getChargingPreferences","getPositionsFromPath","pathLike","buildLocationsString","routePlanningLocationTypes","useEntryPoint","waypointInputs","waypointInput","lngLatString","getWaypointProps","buildLocationsStringFromWaypoints","types","firstPoint","firstRoutePlanningLocation","lastRoutePlanningLocation","lastPoint","positions","getFirstAndLastPoints","toLatLngPointApi","buildlocationsPostData","useEntryPoints","supportingPoints","pointWaypoints","routePlanningLocation","routePlanningLocationIndex","pathRoutePlanningLocation","supportingPointsLengthBeforePath","sections","leg","legIndex","supportingPointIndex","startPointIndex","waypointSourceType","appendPathPostData","waypoint","appendWaypointPostData","buildCalculateRouteRequest","getRoutePlanningLocationType","guidance","version","phonetics","appendGuidanceParams","instructionsInclude","effectiveSectionTypes","inputSectionTypes","sectionType","appendSectionTypes","representation","extendedRouteRepresentations","postData","pathsIncluded","isLdevr","vehicleModel","chargingParameters","toCurrentType","apiCurrentType","toChargingStop","chargingInformationAtEndOfLeg","chargingConnectionInfo","chargingParkLocation","coordinate","addressParts","street","houseNumber","freeformAddress","chargingParkId","streetName","city","municipality","region","countrySubdivision","postalCode","country","plugType","chargingPlugType","currentInA","chargingCurrentInA","voltageInV","chargingVoltageInV","chargingPowerInkW","chargingCurrentType","targetChargeInPCT","targetChargeInkWh","chargingParkPowerInkW","chargingParkSpeed","parseSummary","apiSummary","lengthInMeters","historicTrafficTravelTimeInSeconds","liveTrafficIncidentsTravelTimeInSeconds","noTrafficTravelTimeInSeconds","trafficDelayInSeconds","trafficLengthInMeters","travelTimeInSeconds","departureTime","arrivalTime","deviationDistanceInMeters","deviationDistance","fuelConsumptionInLiters","deviationPoint","totalChargingTimeInSeconds","batteryConsumptionInkWh","batteryConsumptionInPCT","remainingChargeAtArrivalInkWh","remainingChargeAtArrivalInPCT","parseLegSectionProps","apiLegs","reduce","accumulatedParsedLegs","nextApiLeg","currentIndex","lastLegEndPointIndex","endPointIndex","points","toSectionProps","apiSection","toRoadStretchSectionProps","index","importantRoadStretchIndex","roadNumbers","roadNumber","toCountrySectionProps","countryCodeISO3","countryCode","toVehicleRestrictedSectionProps","toTrafficCategories","tec","causes","cause","tecMainCauseCode","calculateTrafficCategory","mainCauseCode","simpleCategory","toTrafficSectionProps","delayInSeconds","effectiveSpeedInKmh","categories","magnitudeOfDelay","indexedMagnitudes","toLaneSectionProps","lanes","laneSeparators","toSpeedLimitSectionProps","maxSpeedLimitInKmh","toRoadShieldsSectionProps","roadShieldReferences","ensureInit","getSectionMapping","mappingFunction","parseSections","apiRoute","legs","apiSections","sectionMapping","mappedSection","parseSectionsAndAppendToResult","DELTA","similar","parseGuidance","apiGuidance","instructions","lastInstructionPathIndex","apiInstruction","maneuverPoint","pathIndex","pathPointIndex","routePath","apiPoint","parseCalculateRouteResponse","routes","apiLeg","progress","parseRoute","calculateRouteTemplate","buildTrafficIncidentDetailsRequest","trafficModelId","categoryFilter","trafficIncidentToIconCategory","timeValidityFilter","appendOptionalParams","resolvedBBox","ids","parseEvent","apiEvent","iconToTrafficIncidentCategory","iconCategory","parseIncident","apiIncident","p","events","delay","timeValidity","probabilityOfOccurrence","numberOfReports","lastReportTime","tmc","apiTMC","tableNumber","tableVersion","direction","location","parseTrafficIncidentDetailsResponse","incidents","trafficIncidentDetailsTemplate","trafficIncidentCategories","customizeService","reverseGeocode","revgeoCustomize","geocode","geocodeCustomize","geometryDataCustomize","geometrySearchCustomize","calculateRoute","routingCustomize","reachableRangeCustomize","evChargingStationsAvailability","evChargingStationsAvailabilityCustomize","trafficIncidentDetails","placeByID","placeByIdCustomize","autocompleteCustomize","getPlaceWithEVAvailability","availabilityId","chargingAvailability","console","getPlacesWithEVAvailability","places","options","enhancedPlaces","placeWithAvailability","excludeIfAvailabilityUnknown","hasChargingAvailability","geocodeOne","geometryResult","placesIdMap","acc","geometryId","placeCoordinates","mergePlacesWithGeometries","placeById","calculateReachableRange","calculateReachableRanges","paramsArray","signal","throwIfAborted","fuzzySearchRequestOptional","maxFuzzyLevel","fuzzySearchRequestSchema","queryIntentApiToSdk","intentApi","intent","details","fuzzySearchTemplate","queryIntent","search","fuzzySearch","searchOne"],"mappings":"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"}
1
+ {"version":3,"file":"services.es.js","sources":["../src/shared/types/apiResponseErrorTypes.ts","../src/shared/errors.ts","../src/shared/schema/commonParamsSchema.ts","../src/shared/schema/validation.ts","../src/shared/serviceTemplate.ts","../src/shared/fetch.ts","../src/shared/schema/geometriesSchema.ts","../src/autocomplete-search/autocompleteSearchRequestSchema.ts","../src/shared/request/requestBuildingUtils.ts","../src/shared/request/commonSearchRequestBuilder.ts","../src/autocomplete-search/requestBuilder.ts","../src/shared/geometry.ts","../src/autocomplete-search/responseParser.ts","../src/autocomplete-search/autocompleteSearchTemplate.ts","../src/autocomplete-search/autocompleteSearch.ts","../src/autocomplete-search/customize.ts","../src/ev-charging-stations-availability/evChargingStationsAvailabilityRequestSchema.ts","../src/shared/types/commonRoutingParams.ts","../src/ev-charging-stations-availability/requestBuilder.ts","../src/shared/ev.ts","../src/ev-charging-stations-availability/connectorAvailability.ts","../src/shared/searchResultParsing.ts","../src/ev-charging-stations-availability/responseParser.ts","../src/ev-charging-stations-availability/evChargingStationsAvailabilityTemplate.ts","../src/ev-charging-stations-availability/evChargingStationsAvailabilityResponseErrorParser.ts","../src/ev-charging-stations-availability/customize.ts","../src/shared/schema/commonGeocodeAndFuzzySearchParamsSchema.ts","../src/shared/schema/commonPlacesParamsSchema.ts","../src/geocode/geocodingRequestSchema.ts","../src/shared/arrays.ts","../src/geocode/requestBuilder.ts","../src/geocode/responseParser.ts","../src/geocode/geocodingTemplate.ts","../src/geocode/customize.ts","../src/geometry-data/geometryDataRequestSchema.ts","../src/geometry-data/requestBuilder.ts","../src/geometry-data/responseParser.ts","../src/geometry-data/geometryDataTemplate.ts","../src/geometry-data/customize.ts","../src/search/commonSearchParamsSchema.ts","../src/geometry-search/geometrySearchRequestSchema.ts","../src/geometry-search/requestBuilder.ts","../src/geometry-search/responseParser.ts","../src/geometry-search/geometrySearchTemplate.ts","../src/geometry-search/geometrySearch.ts","../src/geometry-search/customize.ts","../src/place-by-id/placeByIdSchema.ts","../src/place-by-id/requestBuilder.ts","../src/place-by-id/responseParser.ts","../src/place-by-id/placeByIdTemplate.ts","../src/place-by-id/customize.ts","../src/routing/routingResponseErrorParser.ts","../src/shared/schema/vehicleParamsSchema.ts","../src/shared/types/vehicleRestrictionParams.ts","../src/shared/schema/commonRoutingRequestSchema.ts","../src/reachable-range/types/reachableRangeParams.ts","../src/reachable-range/reachableRangeRequestSchema.ts","../src/shared/request/routingVehicleParamsBuilder.ts","../src/shared/request/commonRoutingRequestBuilder.ts","../src/reachable-range/requestBuilder.ts","../src/reachable-range/responseParser.ts","../src/reachable-range/reachableRangeTemplate.ts","../src/reachable-range/customize.ts","../src/revgeo/requestBuilder.ts","../src/revgeo/responseParser.ts","../src/revgeo/revGeocodeRequestSchema.ts","../src/revgeo/reverseGeocodingTemplate.ts","../src/revgeo/customize.ts","../src/routing/calculateRouteRequestSchema.ts","../src/routing/requestBuilder.ts","../src/routing/responseParser.ts","../src/routing/calculateRouteTemplate.ts","../src/routing/customize.ts","../src/traffic-incident-details/requestBuilder.ts","../src/traffic-incident-details/responseParser.ts","../src/traffic-incident-details/trafficIncidentDetailsTemplate.ts","../src/traffic-incident-details/trafficIncidentDetailsRequestSchema.ts","../src/customize/index.ts","../src/traffic-incident-details/customize.ts","../src/ev-charging-stations-availability/evChargingStationsAvailability.ts","../src/geocode/geocoding.ts","../src/geometry-data/geometryData.ts","../src/place-by-id/placeById.ts","../src/reachable-range/calculateReachableRange.ts","../src/revgeo/reverseGeocoding.ts","../src/routing/calculateRoute.ts","../src/fuzzy-search/fuzzySearchRequestSchema.ts","../src/fuzzy-search/responseParser.ts","../src/fuzzy-search/fuzzySearchTemplate.ts","../src/fuzzy-search/requestBuilder.ts","../src/search/search.ts","../src/fuzzy-search/fuzzySearch.ts","../src/traffic-incident-details/trafficIncidentDetails.ts"],"sourcesContent":["/**\n * @ignore\n */\nexport interface BaseAPIResponseErrorBody {\n /*\n * HTTP error code.\n */\n httpStatusCode: number;\n /*\n * Detailed information about the error.\n */\n detailedError: {\n /*\n * One of the defined error codes.\n */\n code: string;\n /*\n * A human-readable representation of the error code.\n */\n message: string;\n /*\n * Target of the particular error.\n * Value: The name of the request parameter.\n */\n target: string;\n };\n}\n\n/**\n * @ignore\n */\nexport interface DefaultAPIResponseErrorBody extends BaseAPIResponseErrorBody {\n /*\n * A human-readable description of the error code.\n */\n error?: string;\n errorText?: string;\n}\n\n/**\n * @ignore\n */\nexport interface RoutingAPIResponseError {\n /*\n * \tThe format version\n */\n formatVersion: string;\n error: {\n /*\n * A human-readable representation of the error code.\n */\n description: string;\n };\n detailedError: {\n /*\n * A human-readable representation of the error code.\n */\n message: string;\n /*\n * One of the defined error codes.\n */\n code: string;\n };\n}\n\n/**\n * Error returned by an API.\n * @ignore\n */\nexport type APIErrorResponse<T = DefaultAPIResponseErrorBody> = {\n status?: number;\n message: string;\n data?: T;\n};\n\n/**\n * @ignore\n */\nexport enum APICode {\n TOO_MANY_REQUESTS = 429,\n FORBIDDEN = 403,\n}\n","import type { ZodIssue } from 'zod';\nimport type { ValidationError } from './schema/validation';\nimport type { ParseResponseError } from './serviceTypes';\nimport type { APIErrorResponse, DefaultAPIResponseErrorBody } from './types/apiResponseErrorTypes';\nimport { APICode } from './types/apiResponseErrorTypes';\nimport type { ServiceName } from './types/servicesTypes';\n\n/**\n * Base error class for all SDK-related errors.\n *\n * The SDK handles two distinct categories of errors:\n * 1. **Programming errors**: Configuration or usage errors in the user's application,\n * such as passing incorrect types to parameters or functions.\n * 2. **API errors**: Recoverable errors that occur during SDK operations,\n * such as network failures or invalid API responses.\n *\n * @example\n * ```typescript\n * try {\n * // SDK operation\n * } catch (error) {\n * if (error instanceof SDKError) {\n * console.error(`Error in ${error.service}: ${error.message}`);\n * }\n * }\n * ```\n *\n * @group Errors\n */\nexport class SDKError extends Error {\n /**\n * Creates a new SDKError instance.\n *\n * @param message - Human-readable error description\n * @param service - Name of the service where the error occurred\n * @param issues - Optional array of Zod validation issues for detailed error information\n */\n constructor(\n message: string,\n readonly service: string,\n readonly issues?: ZodIssue[],\n ) {\n super(message);\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, SDKError);\n }\n }\n}\n\n/**\n * Mapping of API error codes to human-readable error messages.\n *\n * Provides standardized error messages for common API response codes,\n * ensuring consistent error handling across the SDK.\n *\n * @group Errors\n */\nexport const APIErrorCode: { readonly [K in APICode as number]: string } = {\n [APICode.TOO_MANY_REQUESTS]: 'Too Many Requests: The API Key is over QPS (Queries per second)',\n [APICode.FORBIDDEN]: 'Request failed with status code 403',\n};\n\n/**\n * Error class for HTTP API response errors.\n *\n * Extends {@link SDKError} to include HTTP status codes and automatically\n * maps known error codes to user-friendly messages using {@link APIErrorCode}.\n *\n * @example\n * ```typescript\n * throw new SDKServiceError('Invalid request', 'geocoding', 400);\n * ```\n *\n * @group Errors\n */\nexport class SDKServiceError extends SDKError {\n /**\n * HTTP status code of the failed API request.\n *\n * Common values:\n * - `400`: Bad Request\n * - `403`: Forbidden\n * - `429`: Too Many Requests\n * - `500`: Internal Server Error\n */\n status?: number;\n\n /**\n * Creates a new SDKServiceError instance.\n *\n * If the status code matches a known error in {@link APIErrorCode},\n * the message will be automatically replaced with the standardized message.\n *\n * @param message - Error message from the API or custom message\n * @param service - Name of the service that generated the error\n * @param status - HTTP status code of the failed request\n */\n constructor(message: string, service: string, status?: number) {\n super(message, service);\n this.status = status;\n\n /*\n * We use as message what returns from API if any, otherwise we have our APIErrorCode as a fallback\n * Check if there is a status and if the status exists in the mapped API error types\n */\n if (this.status && APIErrorCode[this.status]) {\n this.message = APIErrorCode[this.status];\n }\n }\n}\n\n/**\n * @ignore\n * @param error\n * @param serviceName\n */\nexport const parseDefaultResponseError: ParseResponseError<DefaultAPIResponseErrorBody> = (error, serviceName) => {\n const { data, message, status } = error;\n // Different services uses property error or errorText or detailedError\n // Here we cover all situations as a default error parser\n const errorMessage = data?.error || data?.errorText || message;\n return new SDKServiceError(errorMessage, serviceName, status);\n};\n\n/**\n * @ignore\n * Generate error for APIResponse, any other error type will be returned as it is.\n * @param error The error captured by a catch function.\n * @param serviceName The name of the service.\n * @param parseResponseError\n */\nexport const buildResponseError = (\n error: unknown,\n serviceName: ServiceName,\n parseResponseError?: ParseResponseError<unknown>,\n): SDKError => {\n if ((error as APIErrorResponse).status) {\n const fetchError = error as APIErrorResponse;\n if (parseResponseError) {\n return parseResponseError(fetchError, serviceName);\n }\n return parseDefaultResponseError(fetchError, serviceName);\n }\n\n return new SDKError((error as Error).message, serviceName);\n};\n\n/**\n * @ignore\n * @param error\n * @param serviceName\n */\nexport const buildValidationError = (error: ValidationError, serviceName: ServiceName): SDKError =>\n new SDKError(error.message, serviceName, error.issues);\n","import { z } from 'zod';\n\n/**\n * @ignore\n */\nexport const commonServiceRequestSchema = z.object({\n apiKey: z.string().optional().describe('TomTom API key for authentication'),\n commonBaseURL: z.string().optional().describe('Common base URL for all services'),\n customServiceBaseURL: z.string().optional().describe('Custom base URL for specific service'),\n language: z.string().optional().describe('Language code for response text (e.g., \"en-US\", \"nl-NL\")'),\n});\n","import type { ZodError } from 'zod';\nimport type { CommonServiceParams } from '../serviceTypes';\nimport type { RequestValidationConfig } from '../types/validation';\nimport { commonServiceRequestSchema } from './commonParamsSchema';\n\n/**\n * Format a Zod error into a human-readable string\n * @ignore\n */\nconst formatZodError = (error: ZodError): string => {\n return error.issues\n .map((issue) => {\n const path = issue.path.length > 0 ? `${issue.path.join('.')}: ` : '';\n return `${path}${issue.message}`;\n })\n .join('; ');\n};\n\n/**\n * Validate Error Class for validating params input, this will be used by SDKError class.\n * @ignore\n */\nexport class ValidationError extends Error {\n issues: ZodError['issues'];\n\n constructor(zodError: ZodError) {\n super(formatZodError(zodError));\n this.issues = zodError.issues;\n }\n}\n\n/**\n * @ignore\n * @param params\n * @param config\n */\nexport const validateRequestSchema = <T extends CommonServiceParams>(\n params: T,\n config?: RequestValidationConfig,\n): T => {\n const requestSchema = config?.schema\n ? commonServiceRequestSchema.extend(config.schema.shape)\n : commonServiceRequestSchema;\n\n // Apply all refinements using superRefine for better type compatibility in Zod v4\n const finalSchema = requestSchema.superRefine((data, ctx) => {\n // Validate common params\n if (!('commonBaseURL' in data) && !('customServiceBaseURL' in data)) {\n ctx.addIssue({\n code: 'custom',\n message: 'commonBaseURL or customServiceBaseURL is required',\n });\n }\n\n // Apply optional refinements\n if (config?.refinements?.length) {\n for (const refinement of config.refinements) {\n if (!refinement.check(data as T)) {\n ctx.addIssue({\n code: 'custom',\n message: refinement.message,\n });\n }\n }\n }\n });\n\n const validation = finalSchema.safeParse(params);\n if (!validation.success) {\n throw new ValidationError(validation.error);\n }\n\n return params;\n};\n","import { generateTomTomHeaders, mergeFromGlobal } from '@tomtom-org/maps-sdk/core';\nimport { buildResponseError, buildValidationError } from './errors';\nimport type { ValidationError } from './schema/validation';\nimport { validateRequestSchema } from './schema/validation';\nimport type { CommonServiceParams, ServiceTemplate } from './serviceTypes';\nimport type { ServiceName } from './types/servicesTypes';\n\n/**\n * @ignore\n * Template execution of a service call.\n * Any service goes through the same template steps:\n * 1- Build request\n * 2- Send request and get API response\n * 3- Parse and return API response\n * @param params The parameters for that specific service call.\n * @param template The implementation of the template steps.\n * @param serviceName The name of the service.\n */\nexport const callService = async <PARAMS extends CommonServiceParams, ApiRequest, ApiResponse, RESPONSE>(\n params: PARAMS,\n template: ServiceTemplate<PARAMS, ApiRequest, ApiResponse, RESPONSE>,\n serviceName: ServiceName,\n): Promise<RESPONSE> => {\n const customApiVersion = template.getAPIVersion?.(params);\n const mergedParams = mergeFromGlobal({ ...params, ...(customApiVersion && { apiVersion: customApiVersion }) });\n // (params.validateRequest defaults to true, thus true and undefined are the same)\n if (params.validateRequest === undefined || params.validateRequest) {\n try {\n validateRequestSchema<PARAMS>(mergedParams, template.requestValidation);\n } catch (e) {\n return Promise.reject(buildValidationError(e as ValidationError, serviceName));\n }\n }\n const apiRequest = template.buildRequest(mergedParams);\n const headers = generateTomTomHeaders(mergedParams);\n params.onAPIRequest?.(apiRequest);\n\n try {\n const apiResponse = await template.sendRequest(apiRequest, headers);\n params.onAPIResponse?.(apiRequest, apiResponse);\n return template.parseResponse(await apiResponse.data, mergedParams);\n } catch (e) {\n params.onAPIResponse?.(apiRequest, e);\n return Promise.reject(buildResponseError(e, serviceName, template.parseResponseError));\n }\n};\n","import type { TomTomHeaders } from '@tomtom-org/maps-sdk/core';\nimport type { FetchInput, ParsedFetchResponse, PostObject } from './types/fetch';\n\n/**\n * Custom error class for HTTP fetch errors.\n */\nclass FetchError extends Error {\n public readonly status: number;\n public readonly data?: unknown;\n\n constructor(status: number, message?: string, data?: unknown) {\n super(message ?? `HTTP Error ${status}`);\n this.name = 'FetchError';\n this.status = status;\n this.data = data;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, FetchError);\n }\n }\n}\n\n// Returns the response as a JSON object or throws an error if the response isn't successful.\nconst returnOrThrow = async <T>(response: Response): ParsedFetchResponse<T> => {\n if (response.ok) {\n return { data: await response.json(), status: response.status };\n }\n let message: string | undefined;\n let errorBody;\n const contentType = response.headers.get('content-type');\n if (response.bodyUsed) {\n message = response.statusText;\n } else if (contentType?.includes('application/json')) {\n errorBody = await response.json();\n message = errorBody?.errorText ?? errorBody?.message ?? errorBody?.detailedError?.message;\n } else if (contentType?.includes('text/xml')) {\n errorBody = await response.text();\n message = response.statusText;\n }\n\n throw new FetchError(response.status, message, errorBody);\n};\n\n/**\n * Fetches the given HTTP JSON resource with an HTTP GET request and returns a promise with the response as a JSON object.\n * If the response isn't successful, it returns a rejected promise with the http error code.\n * @ignore\n * @param url The URL to fetch.\n * @param headers The headers to be sent with the request.\n */\nexport const get = async <T>(url: URL, headers: TomTomHeaders): ParsedFetchResponse<T> =>\n returnOrThrow(await fetch(url, { headers }));\n\n/**\n * Fetches the given HTTP JSON resource with an HTTP POST request and returns a promise with the response as a JSON object.\n * If the response isn't successful, it returns a rejected promise with the http error code.\n * @ignore\n * @param input The POST object with URL and optional payload.\n * @param headers The headers to be sent with the request.\n */\nexport const post = async <T, D>(input: PostObject<D>, headers: TomTomHeaders): ParsedFetchResponse<T> =>\n returnOrThrow(\n await fetch(input.url, {\n method: 'POST',\n body: JSON.stringify(input.data),\n headers: { ...headers, 'Content-Type': 'application/json' },\n }),\n );\n\n/**\n * Fetches the given HTTP JSON resource with the given HTTP operation and URL/Payload as applicable.\n * * Useful for services which can use different HTTP methods depending on the parameters.\n * @param input The input object (e.g. containing either GET or POST data)\n * @param headers The headers to be sent with the request.\n * @ignore\n */\nexport const fetchWith = async <T, D = void>(input: FetchInput<D>, headers: TomTomHeaders): ParsedFetchResponse<T> => {\n const method = input.method;\n if (method === 'GET') {\n return get<T>(input.url, headers);\n }\n if (method === 'POST') {\n return post<T, D>(input, headers);\n }\n throw new Error(`Unsupported HTTP method received: ${method}`);\n};\n","import { z } from 'zod';\n\n/**\n * @ignore\n */\nexport const lineStringCoordsSchema = z\n .array(z.array(z.number()))\n .describe('Array of coordinate arrays representing a line string');\n\n/**\n * @ignore\n */\nexport const geometrySchema = z\n .object({\n type: z\n .enum([\n 'Point',\n 'MultiPoint',\n 'LineString',\n 'MultiLineString',\n 'Polygon',\n 'MultiPolygon',\n 'GeometryCollection',\n 'Circle',\n ])\n .describe('GeoJSON geometry type'),\n coordinates: z\n .union([\n z.array(z.number()),\n lineStringCoordsSchema,\n z.array(z.array(z.array(z.number()))),\n z.array(z.array(z.array(z.array(z.number())))),\n ])\n .describe('Coordinate array(s) for the geometry'),\n radius: z.optional(z.number()).describe('Radius for Circle geometries'),\n radiusMeters: z.optional(z.number()).describe('Radius in meters for Circle geometries'),\n bbox: z.optional(z.array(z.number())).describe('Bounding box [minLng, minLat, maxLng, maxLat]'),\n })\n .check(\n z.refine(\n (data) => (data.type === 'Circle' ? Boolean(data.radius) : true),\n 'type: \"Circle\" must have radius property',\n ),\n );\n\n/**\n * @ignore\n */\nexport const featureSchema = z.object({\n type: z.literal('Feature').describe('GeoJSON type identifier'),\n geometry: geometrySchema.describe('GeoJSON geometry object'),\n id: z.optional(z.union([z.string(), z.number()])).describe('Optional feature identifier'),\n properties: z.any().describe('Feature properties'),\n bbox: z.optional(z.array(z.number())).describe('Bounding box [minLng, minLat, maxLng, maxLat]'),\n});\n\n/**\n * @ignore\n */\nexport const featureCollectionSchema = z.object({\n type: z.literal('FeatureCollection').describe('GeoJSON type identifier'),\n features: z.array(featureSchema).describe('Array of GeoJSON features'),\n id: z.optional(z.union([z.string(), z.number()])).describe('Optional collection identifier'),\n properties: z.any().describe('Collection properties'),\n bbox: z.optional(z.array(z.number())).describe('Bounding box [minLng, minLat, maxLng, maxLat]'),\n});\n\n/**\n * @ignore\n */\nexport const hasLngLatSchema = z\n .union([\n z.tuple([z.number().min(-180).max(180), z.number().min(-90).max(90)]),\n z.tuple([z.number().min(-180).max(180), z.number().min(-90).max(90), z.number()]),\n z.object({\n type: z.literal('Point'),\n coordinates: z.array(z.number()),\n }),\n featureSchema,\n ])\n .describe('Geographic position as [longitude, latitude] tuple, Point geometry, or Feature');\n\n/**\n * @ignore\n */\nconst geoJsonbBoxSchema = z\n .union([\n z.array(z.number()).refine((arr) => arr.length === 4, { message: 'BBox must have 4 elements' }),\n z.array(z.number()).refine((arr) => arr.length === 6, { message: 'BBox must have 6 elements' }),\n ])\n .describe(\n 'GeoJSON bounding box array [minLng, minLat, maxLng, maxLat] or [minLng, minLat, minAlt, maxLng, maxLat, maxAlt]',\n );\n\n/**\n * @ignore\n */\nexport const GeoJSONSchema = z\n .union([geometrySchema, featureSchema, featureCollectionSchema])\n .describe('Any GeoJSON object (Geometry, Feature, or FeatureCollection)');\n\n/**\n * @ignore\n */\nexport const hasBBoxSchema = z\n .union([geoJsonbBoxSchema, GeoJSONSchema, z.array(GeoJSONSchema)])\n .describe('Bounding box as array, GeoJSON object, or array of GeoJSON objects');\n","import { z } from 'zod';\nimport { hasLngLatSchema } from '../shared/schema/geometriesSchema';\n\nconst autocompleteSearchRequestMandatory = z.object({\n query: z.string().describe('Partial search query for autocomplete suggestions'),\n});\n\nconst autocompleteSearchRequestOptional = z.object({\n position: hasLngLatSchema.optional().describe('Geographic position [longitude, latitude] to bias search results'),\n limit: z.number().max(100).optional().describe('Maximum number of autocomplete suggestions to return (1-100)'),\n radiusMeters: z.number().optional().describe('Search radius in meters around the specified position'),\n countries: z.array(z.string()).optional().describe('Country codes to restrict search results (ISO 3166-1 alpha-2)'),\n resultType: z.array(z.string()).optional().describe('Types of results to include in suggestions'),\n});\n\n/**\n * @ignore\n */\nexport const autocompleteSearchRequestSchema = autocompleteSearchRequestMandatory.extend(\n autocompleteSearchRequestOptional.shape,\n);\n","import type { HasLngLat, POICategory } from '@tomtom-org/maps-sdk/core';\nimport { getPosition, poiCategoriesToID } from '@tomtom-org/maps-sdk/core';\nimport { isNil } from 'lodash-es';\nimport type { CommonServiceParams } from '../serviceTypes';\n\n/**\n * @ignore\n * @param urlParams\n * @param params\n */\nexport const appendCommonParams = (urlParams: URLSearchParams, params: CommonServiceParams): void => {\n urlParams.append('apiVersion', String(params.apiVersion));\n\n // TODO: restore apiAccessToken if we implement oauth2 access:\n // if (!params.apiAccessToken) {\n urlParams.append('key', params.apiKey as string);\n // }\n\n params.language && urlParams.append('language', params.language);\n};\n\n/**\n * Adds parameter from the array by repeating each array part into a query parameter of the same name.\n * E.g. ...&avoid=motorways&avoid=ferries&...\n * @ignore\n * @param urlParams\n * @param paramName\n * @param paramArray\n */\nexport const appendByRepeatingParamName = (\n urlParams: URLSearchParams,\n paramName: string,\n paramArray?: string[],\n): void => {\n for (const param of paramArray || []) {\n urlParams.append(paramName, param);\n }\n};\n\n/**\n * @ignore\n */\nexport const appendByJoiningParamValue = (\n urlParams: URLSearchParams,\n name: string,\n values?: string[] | number[] | (string | number)[],\n): void => {\n if (Array.isArray(values) && values.length > 0) {\n urlParams.append(name, values.join(','));\n }\n};\n\n/**\n * @ignore\n */\nexport const appendOptionalParam = (\n urlParams: URLSearchParams,\n name: string,\n value?: string | number | boolean,\n): void => {\n !isNil(value) && urlParams.append(name, String(value));\n};\n\n/**\n * Adds lat and lon parameters to the url.\n * @ignore\n * @param urlParams\n * @param hasLngLat\n */\nexport const appendLatLonParamsFromPosition = (urlParams: URLSearchParams, hasLngLat: HasLngLat | undefined): void => {\n const position = getPosition(hasLngLat);\n if (position) {\n urlParams.append('lat', String(position[1]));\n urlParams.append('lon', String(position[0]));\n }\n};\n\n/**\n * map human-readable poi categories to their ID.\n * @ignore\n * @param poiCategories\n */\nexport const mapPOICategoriesToIDs = (poiCategories: (number | POICategory)[]): number[] => {\n return poiCategories.map((poiCategory) => {\n if (typeof poiCategory !== 'number') {\n return poiCategoriesToID[poiCategory];\n }\n return poiCategory;\n });\n};\n","import type { FuzzySearchParams } from '../../fuzzy-search';\nimport type { GeometrySearchParams } from '../../geometry-search';\nimport {\n appendByJoiningParamValue,\n appendCommonParams,\n appendLatLonParamsFromPosition,\n appendOptionalParam,\n mapPOICategoriesToIDs,\n} from './requestBuildingUtils';\n\n/**\n * @ignore\n */\nexport const PLACES_URL_PATH = '/maps/orbis/places';\n\n/**\n * Appends request parameters common to search APIs such as fuzzy + geometry search.\n * * Mutates the given searchURL with the appended parameters.\n * @param searchUrl The search URL to append parameters to. Should come without any parameters at this point.\n * @param params The search parameters, with global configuration already merged into them.\n */\nexport const appendCommonSearchParams = (searchUrl: URL, params: FuzzySearchParams | GeometrySearchParams): void => {\n const urlParams = searchUrl.searchParams;\n appendCommonParams(urlParams, params);\n appendOptionalParam(urlParams, 'limit', params.limit);\n appendLatLonParamsFromPosition(urlParams, params.position);\n\n appendByJoiningParamValue(urlParams, 'fuelSet', params.fuelTypes);\n appendByJoiningParamValue(urlParams, 'idxSet', params.indexes);\n appendByJoiningParamValue(urlParams, 'brandSet', params.poiBrands);\n params.poiCategories &&\n appendByJoiningParamValue(urlParams, 'categorySet', mapPOICategoriesToIDs(params.poiCategories));\n appendByJoiningParamValue(urlParams, 'connectorSet', params.connectors);\n appendByJoiningParamValue(urlParams, 'mapcodes', params.mapcodes);\n appendByJoiningParamValue(urlParams, 'extendedPostalCodesFor', params.extendedPostalCodesFor);\n\n appendOptionalParam(urlParams, 'minPowerKW', params.minPowerKW);\n appendOptionalParam(urlParams, 'maxPowerKW', params.maxPowerKW);\n appendOptionalParam(urlParams, 'view', params.view);\n appendOptionalParam(urlParams, 'openingHours', params.openingHours);\n appendOptionalParam(urlParams, 'timeZone', params.timeZone);\n appendOptionalParam(urlParams, 'relatedPois', params.relatedPois);\n appendByJoiningParamValue(urlParams, 'entityTypeSet', params.geographyTypes);\n};\n","import { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport {\n appendByJoiningParamValue,\n appendCommonParams,\n appendLatLonParamsFromPosition,\n appendOptionalParam,\n} from '../shared/request/requestBuildingUtils';\nimport type { AutocompleteSearchParams } from './types';\n\nconst buildUrlBasePath = (mergedOptions: AutocompleteSearchParams): string =>\n mergedOptions.customServiceBaseURL ||\n `${mergedOptions.commonBaseURL}${PLACES_URL_PATH}/autocomplete/${mergedOptions.query}.json`;\n\n/**\n * Default function for building autocomplete request from {@link AutocompleteSearchParams}\n * @param params The autocomplete parameters, with global configuration already merged into them.\n */\nexport const buildAutocompleteSearchRequest = (params: AutocompleteSearchParams): URL => {\n const url = new URL(`${buildUrlBasePath(params)}`);\n const urlParams = url.searchParams;\n /**\n * Auto-complete service defaults the language to en-GB if not specified explicitly as service param\n * Or global config\n */\n params.language = params.language ?? 'en-GB';\n appendCommonParams(urlParams, params);\n appendOptionalParam(urlParams, 'limit', params.limit);\n appendLatLonParamsFromPosition(urlParams, params.position);\n appendByJoiningParamValue(urlParams, 'countrySet', params.countries);\n appendOptionalParam(urlParams, 'radius', params.radiusMeters);\n appendByJoiningParamValue(urlParams, 'resultSet', params.resultType);\n\n return url;\n};\n","import type { BBox } from '@tomtom-org/maps-sdk/core';\nimport type { Position } from 'geojson';\nimport type { BoundingBoxAPI, BoundingBoxTopLeftAPI, LatLonAPI } from './types/apiPlacesResponseTypes';\n\n/**\n * @ignore\n * @param csv\n */\nexport const csvLatLngToPosition = (csv: string): Position => {\n const splitLatLng = csv.split(',');\n return [Number(splitLatLng[1]), Number(splitLatLng[0])];\n};\n\n/**\n * @ignore\n * @param position\n */\nexport const positionToCSVLatLon = (position: Position): string => `${position[1]},${position[0]}`;\n\nconst hasTopLeftPoint = (bbox: BoundingBoxAPI): bbox is BoundingBoxTopLeftAPI => {\n return (<BoundingBoxTopLeftAPI>bbox).topLeftPoint !== undefined;\n};\n\n/**\n * @ignore\n * @param apiBBox\n */\nexport const apiToGeoJSONBBox = (apiBBox: BoundingBoxAPI): BBox => {\n let westSouth: Position;\n let eastNorth: Position;\n if (hasTopLeftPoint(apiBBox)) {\n westSouth = [apiBBox.topLeftPoint.lon, apiBBox.btmRightPoint.lat];\n eastNorth = [apiBBox.btmRightPoint.lon, apiBBox.topLeftPoint.lat];\n } else {\n westSouth = csvLatLngToPosition(apiBBox.southWest);\n eastNorth = csvLatLngToPosition(apiBBox.northEast);\n }\n return [westSouth[0], westSouth[1], eastNorth[0], eastNorth[1]];\n};\n\n/**\n * @ignore\n * @param point\n */\nexport const latLonAPIToPosition = (point: LatLonAPI): Position => {\n return [point.lon, point.lat];\n};\n","import { latLonAPIToPosition } from '../shared/geometry';\nimport type { AutocompleteSearchResponse, AutocompleteSearchResponseAPI } from './types';\n\n/**\n * Default function to parse autocomplete response.\n * @param apiResponse The API response.\n */\nexport const parseAutocompleteSearchResponse = (\n apiResponse: AutocompleteSearchResponseAPI,\n): AutocompleteSearchResponse => {\n const { position, ...geoBias } = apiResponse.context.geoBias || {};\n return {\n ...apiResponse,\n context: {\n ...apiResponse.context,\n geoBias: {\n ...(position && { position: latLonAPIToPosition(position) }),\n radiusMeters: geoBias.radius,\n },\n },\n };\n};\n","import type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { autocompleteSearchRequestSchema } from './autocompleteSearchRequestSchema';\nimport { buildAutocompleteSearchRequest } from './requestBuilder';\nimport { parseAutocompleteSearchResponse } from './responseParser';\nimport type { AutocompleteSearchParams, AutocompleteSearchResponse, AutocompleteSearchResponseAPI } from './types';\n\n/**\n * Autocomplete service template type.\n * @ignore\n */\nexport type AutocompleteSearchTemplate = ServiceTemplate<\n AutocompleteSearchParams,\n URL,\n AutocompleteSearchResponseAPI,\n AutocompleteSearchResponse\n>;\n\n/**\n * Autocomplete service template main implementation.\n * @ignore\n */\nexport const autocompleteSearchTemplate: AutocompleteSearchTemplate = {\n requestValidation: { schema: autocompleteSearchRequestSchema },\n buildRequest: buildAutocompleteSearchRequest,\n sendRequest: get,\n parseResponse: parseAutocompleteSearchResponse,\n};\n","import { callService } from '../shared/serviceTemplate';\nimport type { AutocompleteSearchTemplate } from './autocompleteSearchTemplate';\nimport { autocompleteSearchTemplate } from './autocompleteSearchTemplate';\nimport type { AutocompleteSearchParams, AutocompleteSearchResponse } from './types';\n\n/**\n * Autocomplete search queries as the user types, enabling faster and more accurate search.\n *\n * The Autocomplete service recognizes entities (places, addresses, POIs) within a partial\n * input query and offers them as completion suggestions. This enables real-time search\n * assistance and improves the search experience.\n *\n * @remarks\n * Key features:\n * - **Real-time suggestions**: Returns results as the user types\n * - **Entity recognition**: Identifies addresses, POIs, and geographic areas\n * - **Structured results**: Provides both plain text and structured data\n * - **Query refinement**: Helps users formulate more accurate search queries\n * - **Fast response**: Optimized for low-latency interactive use\n *\n * Typical use cases:\n * - Search box autocomplete dropdowns\n * - Address entry forms\n * - Location pickers\n * - Navigation apps\n *\n * @param params - Autocomplete parameters including the partial query\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to autocomplete suggestions\n *\n * @example\n * ```typescript\n * // Autocomplete as user types \"amster\"\n * const suggestions = await autocompleteSearch({\n * key: 'your-api-key',\n * query: 'amster',\n * limit: 5\n * });\n * // Returns: Amsterdam, Amsterdam Centraal, etc.\n *\n * // Autocomplete with position bias\n * const localSuggestions = await autocompleteSearch({\n * key: 'your-api-key',\n * query: 'main st',\n * at: [4.9041, 52.3676], // Near Amsterdam\n * limit: 10\n * });\n *\n * // Autocomplete with category filter\n * const restaurantSuggestions = await autocompleteSearch({\n * key: 'your-api-key',\n * query: 'pizz',\n * categorySet: [7315], // Restaurant category\n * at: [4.9041, 52.3676]\n * });\n * ```\n *\n * @see [Autocomplete API Documentation](https://docs.tomtom.com/search-api/documentation/autocomplete-service/autocomplete)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Search Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/search)\n *\n * @group Autocomplete Search\n */\nexport const autocompleteSearch = async (\n params: AutocompleteSearchParams,\n customTemplate?: Partial<AutocompleteSearchTemplate>,\n): Promise<AutocompleteSearchResponse> =>\n callService(params, { ...autocompleteSearchTemplate, ...customTemplate }, 'Autocomplete');\n\nexport default autocompleteSearch;\n","import { autocompleteSearch } from './autocompleteSearch';\nimport type { AutocompleteSearchTemplate } from './autocompleteSearchTemplate';\nimport { autocompleteSearchTemplate } from './autocompleteSearchTemplate';\nimport { buildAutocompleteSearchRequest } from './requestBuilder';\nimport { parseAutocompleteSearchResponse } from './responseParser';\n\nconst customize: {\n autocompleteSearch: typeof autocompleteSearch;\n buildAutocompleteSearchRequest: typeof buildAutocompleteSearchRequest;\n parseAutocompleteSearchResponse: typeof parseAutocompleteSearchResponse;\n autocompleteSearchTemplate: AutocompleteSearchTemplate;\n} = {\n autocompleteSearch,\n buildAutocompleteSearchRequest,\n parseAutocompleteSearchResponse,\n autocompleteSearchTemplate,\n};\nexport default customize;\n","import { z } from 'zod';\nimport { commonServiceRequestSchema } from '../shared/schema/commonParamsSchema';\n\n/**\n * @ignore\n */\nexport const evChargingStationsAvailabilityRequestSchema = commonServiceRequestSchema.extend({\n id: z.string().describe('Unique identifier of the EV charging station'),\n});\n","import type { Avoidable, HasBBox, TravelMode } from '@tomtom-org/maps-sdk/core';\nimport { VehicleParameters } from './vehicleParams';\n\n/**\n * Basic low/normal/high intensity level option.\n *\n * Used for configuring route characteristics like hilliness or windingness.\n *\n * @remarks\n * - `low`: Minimal intensity\n * - `normal`: Moderate intensity\n * - `high`: Maximum intensity\n *\n * @group Routing\n */\nexport type LNH = 'low' | 'normal' | 'high';\n\n// TODO: there is no slope data yet in Orbis, thus hilliness isn't supported yet\n// /**\n// * Options applicable to the thrilling route type.\n// */\n// export type ThrillingParams = {\n// /**\n// * The level of hilliness on a thrilling route.\n// * * Possible values: low, normal, high.\n// * * This parameter can only be used in conjunction with routeType thrilling.\n// * @default None\n// */\n// hilliness?: LNH;\n//\n// /**\n// * The level of windingness on a thrilling route.\n// *\n// * * Possible values: low, normal, high.\n// * * This parameter can only be used in conjunction with routeType thrilling.\n// * @default None\n// */\n// windingness?: LNH;\n// };\n\n/**\n * Available route types, where each type specifies the type of optimization used when calculating routes:\n * * **fast**: Route calculation is optimized by travel time, while keeping the routes sensible. For example, the calculation may avoid shortcuts along inconvenient side roads or long detours that only save very little time.\n * * **short**: Route calculation is optimized such that a good compromise between small travel time and short travel distance is achieved.\n * * **efficient**: Route calculation is optimized such that a good compromise between small travel time and low fuel or energy consumption is achieved.\n * * **thrilling**: Route calculation is optimized such that routes include interesting or challenging roads and use as few motorways as possible.\n * There is a limit of 900km on routes planned with routeType=thrilling.\n *\n * @group Routing\n */\nexport const routeTypes = ['fast', 'short', 'efficient', 'thrilling'] as const;\n\n/**\n * Route optimization strategy for route calculation.\n *\n * Determines what the routing engine optimizes for when calculating the route.\n * Each type produces different routes suited to different use cases.\n *\n * @remarks\n * **Route Type Strategies:**\n *\n * - **`fast`**: Minimize travel time while maintaining practicality\n * - Prefers major roads and highways\n * - Avoids unnecessary detours and shortcuts on minor roads\n * - Best for most everyday use cases (commuting, business travel)\n *\n * - **`short`**: Balance between time and distance\n * - Good compromise between speed and mileage\n * - May use smaller roads to save distance\n * - Useful for short trips or when fuel costs matter\n *\n * - **`efficient`**: Minimize fuel or energy consumption\n * - Optimizes for least energy use\n * - Considers vehicle consumption model\n * - Avoids rapid acceleration/deceleration\n * - Best used with vehicle consumption parameters\n *\n * - **`thrilling`**: Scenic and engaging routes\n * - Prefers curvy, interesting roads\n * - Minimizes motorway usage\n * - **Limited to 900km maximum route length**\n * - Ideal for motorcycle rides or scenic drives\n *\n * @example\n * ```typescript\n * // Fastest route for commuting\n * const routeType: RouteType = 'fast';\n *\n * // Most fuel-efficient route for long trip\n * const ecoRoute: RouteType = 'efficient';\n *\n * // Scenic route for leisure\n * const scenicRoute: RouteType = 'thrilling';\n * ```\n *\n * @group Routing\n */\nexport type RouteType = (typeof routeTypes)[number];\n\n/**\n * Traffic consideration mode for route calculation.\n *\n * Controls how traffic conditions are factored into routing and travel time estimates.\n *\n * @remarks\n * **Traffic Modes:**\n *\n * - **`live`**: Real-time + historical traffic\n * - Includes current traffic jams and incidents\n * - Considers short-term and long-term road closures\n * - Most accurate for immediate departures\n * - Updates with current conditions\n *\n * - **`historical`**: Typical traffic patterns only\n * - Based on historical data for time of day/week\n * - Ignores current traffic conditions\n * - Good for future trip planning\n * - More predictable for scheduled departures\n *\n * @example\n * ```typescript\n * // Route considering current traffic (departing now)\n * const trafficMode: TrafficInput = 'live';\n *\n * // Route based on typical patterns (planning ahead)\n * const plannedRoute: TrafficInput = 'historical';\n * ```\n *\n * @group Routing\n */\nexport type TrafficInput = 'live' | 'historical';\n\n/**\n * Cost model criteria for route optimization.\n *\n * Defines routing preferences and constraints that influence path selection.\n * Combines route type, traffic consideration, and avoidance criteria to determine\n * what makes a route \"better\" in the eyes of the routing engine.\n *\n * @remarks\n * The cost model affects how the route path is calculated, but does not affect what other data the response includes.\n *\n * The cost model balances multiple factors:\n * - Time efficiency\n * - Distance\n * - Fuel/energy consumption\n * - User preferences (avoid tolls, ferries, etc.)\n * - Traffic conditions\n *\n * @example\n * ```typescript\n * // Fast route avoiding tolls\n * const costModel: CostModel = {\n * routeType: 'fast',\n * traffic: 'live',\n * avoid: ['tollRoads']\n * };\n *\n * // Eco-friendly route avoiding highways\n * const ecoCostModel: CostModel = {\n * routeType: 'efficient',\n * traffic: 'historical',\n * avoid: ['motorways', 'ferries']\n * };\n *\n * // Scenic route for leisure\n * const scenicCostModel: CostModel = {\n * routeType: 'thrilling',\n * avoid: ['motorways', 'tollRoads']\n * };\n * ```\n *\n * @group Routing\n */\nexport type CostModel = {\n /**\n * Specifies something that the route calculation should try to avoid when determining the route.\n * @default None\n */\n avoid?: Avoidable[];\n\n /**\n * Rectangular areas for the routing engine to bypass, each expressed as a {@link HasBBox}.\n *\n * Up to 10 rectangles are supported. Useful for avoiding construction zones,\n * restricted areas, or known congestion points.\n *\n * @remarks\n * Constraints per rectangle:\n * - Maximum size: ~160×160 km\n * - Cannot cross the 180th meridian\n * - Latitude must be between −80° and +80°\n *\n * @example\n * ```typescript\n * // Avoid an area using a BBox array [west, south, east, north]\n * avoidAreas: [\n * [2.265938, 48.81851, 2.41115, 48.90309]\n * ]\n * ```\n */\n avoidAreas?: HasBBox[];\n\n /**\n * Decides how traffic is considered for computing routes.\n *\n * Possible values are:\n * * live: In addition to historical travel times, routing and estimated travel time\n * consider traffic jams and short- and long-term closures during the travel time window.\n * * historical: Routing and estimated travel time consider historical travel times and long term closures.\n * Traffic jams and short-term closures during the travel time window do not influence routing or travel time.\n *\n * @default live\n *\n * @remarks\n * This setting does not affect whether live traffic is included in the response or not.\n * * Considering historical traffic in cost model does not mean live traffic is not included in the response.\n */\n traffic?: TrafficInput;\n\n /**\n * Specifies the type of optimization used when calculating routes.\n * Possible values are:\n *\n * * **fast**: Route calculation is optimized by travel time, while keeping the routes sensible. For example, the calculation may avoid shortcuts along inconvenient side roads or long detours that only save very little time.\n * * **short**: Route calculation is optimized such that a good compromise between small travel time and short travel distance is achieved.\n * * **efficient**: Route calculation is optimized such that a good compromise between small travel time and low fuel or energy consumption is achieved.\n * * **thrilling**: Route calculation is optimized such that routes include interesting or challenging roads and use as few motorways as possible.\n * There is a limit of 900km on routes planned with routeType=thrilling.\n * @default fast\n */\n routeType?: RouteType;\n\n /**\n * Optional parameters if the route type is \"thrilling\" to indicate how curvy and hilly the route should be.\n */\n // TODO not supported yet in Orbis (no slope data)\n // thrillingParams?: ThrillingParams;\n};\n\ntype DepartArriveOption = 'departAt' | 'arriveBy';\n\n/**\n * Departure or arrival time specification for route planning.\n *\n * Allows specifying either when to depart from the origin or when to arrive at the destination.\n * The routing engine calculates the route optimized for that specific time window, considering\n * traffic patterns for that time of day.\n *\n * @typeParam Option - Whether this specifies departure or arrival time\n *\n * @remarks\n * Traffic conditions vary significantly by:\n * - Time of day (rush hour vs off-peak)\n * - Day of week (weekday vs weekend)\n * - Special events or holidays\n *\n * Specifying a departure or arrival time enables the router to:\n * - Use appropriate traffic data for that time\n * - Plan around rush hour or quiet periods\n * - Calculate accurate arrival/departure times\n * - Account for time-dependent road restrictions\n *\n * **Important Notes:**\n * - Times are processed in the timezone of the origin/destination\n *\n * @example\n * ```typescript\n * // Depart at specific time (morning commute)\n * const departParams: DepartArriveParams = {\n * option: 'departAt',\n * date: new Date('2025-10-20T08:00:00Z')\n * };\n *\n * // Arrive by specific time (catch a flight)\n * const arriveParams: DepartArriveParams = {\n * option: 'arriveBy',\n * date: new Date('2025-10-20T14:00:00Z')\n * };\n *\n * // Plan route avoiding rush hour\n * const offPeakDepart: DepartArriveParams = {\n * option: 'departAt',\n * date: new Date('2025-10-20T10:30:00Z') // After morning rush\n * };\n * ```\n *\n * @group Routing\n */\nexport type DepartArriveParams<Option extends DepartArriveOption = DepartArriveOption> = {\n /**\n * Whether to specify a departure or arrival time.\n *\n * @remarks\n * - `departAt`: Calculate route from this departure time forward\n * - `arriveBy`: Calculate route backward to arrive by this time\n */\n option: Option;\n\n /**\n * The date and time to depart or arrive.\n *\n * @remarks\n * If past dates are supplied or dates that are impossible to achieve\n * (e.g., an imminent arrival date for a very long route), the system\n * will default to departing immediately.\n *\n * Times should be specified in ISO 8601 format or as JavaScript Date objects.\n */\n date: Date;\n};\n\n/**\n * Common parameters shared across all routing service requests.\n *\n * These parameters configure how routes are calculated, including optimization\n * strategy, vehicle characteristics, timing constraints, and travel preferences.\n * They provide a consistent interface across different routing services.\n *\n * @remarks\n * Most routing services (calculateRoute, calculateMatrixRoute, calculateReachableRange)\n * accept these parameters to customize route calculation. They control:\n * - What to optimize for (time, distance, fuel)\n * - Vehicle constraints and capabilities\n * - When to travel (affecting traffic)\n * - What features to avoid\n * - Mode of transportation\n *\n * **Service Compatibility:**\n * - {@link calculateRoute}: All parameters supported\n * - {@link calculateMatrixRoute}: Subset of parameters\n * - {@link calculateReachableRange}: Subset of parameters\n *\n * @example\n * ```typescript\n * // Standard car route avoiding tolls\n * const routingParams: CommonRoutingParams = {\n * costModel: {\n * routeType: 'fast',\n * traffic: 'live',\n * avoid: ['tollRoads']\n * },\n * travelMode: 'car',\n * when: {\n * option: 'departAt',\n * date: new Date('2025-10-20T08:00:00Z')\n * }\n * };\n *\n * // Electric vehicle route with consumption model\n * const evRoutingParams: CommonRoutingParams = {\n * costModel: {\n * routeType: 'efficient',\n * traffic: 'live'\n * },\n * travelMode: 'car',\n * vehicle: {\n * engineType: 'electric',\n * model: {\n * dimensions: {\n * weightKG: 2000\n * },\n * engine: {\n * consumption: {\n * speedToConsumption: [\n * { speedKMH: 50, consumptionUnitsPer100KM: 15 },\n * { speedKMH: 90, consumptionUnitsPer100KM: 18 },\n * { speedKMH: 120, consumptionUnitsPer100KM: 22 }\n * ]\n * }\n * }\n * },\n * state: {\n * currentChargeInkWh: 60\n * }\n * }\n * };\n *\n * // Truck route with restrictions\n * const truckParams: CommonRoutingParams = {\n * costModel: {\n * routeType: 'short',\n * avoid: ['tollRoads', 'ferries']\n * },\n * travelMode: 'truck',\n * vehicle: {\n * model: {\n * dimensions: {\n * lengthMeters: 16.5,\n * widthMeters: 2.5,\n * heightMeters: 4.0,\n * weightKG: 40000\n * },\n * restrictions: {\n * restrictions: {\n * commercial: true,\n * maxSpeedKMH: 90\n * }\n * }\n * }\n * }\n * };\n * ```\n *\n * @see [Common Routing Parameters Documentation](https://docs.tomtom.com/routing-api/documentation/routing/common-routing-parameters)\n *\n * @group Routing\n */\nexport type CommonRoutingParams = {\n /**\n * Criteria that specifies what paths to prefer during routing.\n */\n costModel?: CostModel;\n\n /**\n * The primary means of transportation to be used while routing.\n *\n * The travel mode for the requested route.\n * Note that the requested travelMode may not be available for the entire route. Where\n * the requested travelMode is not available for a particular section, the element of the\n * response for that section will be 'other'.\n * @default None\n */\n travelMode?: TravelMode;\n\n /**\n * Specifies when to depart or arrive.\n * If past dates are supplied or in a way that are impossible to achieve\n * (e.g. an imminent arrival date for a long route), then it will default to departing now.\n * @default depart now\n */\n when?: DepartArriveParams;\n\n /**\n * Parameters for the vehicle that will be used to drive the route.\n */\n vehicle?: VehicleParameters;\n\n /**\n * The version of the API to use.\n * * The SDK will use the right default when not specified.\n * * Use it only if you really need to target a specific API version.\n */\n apiVersion?: number;\n};\n","import { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport { appendCommonParams } from '../shared/request/requestBuildingUtils';\nimport type { ChargingStationsAvailabilityParams } from './types/evChargingStationsAvailabilityParams';\n\nconst buildUrlBasePath = (params: ChargingStationsAvailabilityParams): string =>\n params.customServiceBaseURL ?? `${params.commonBaseURL}${PLACES_URL_PATH}/ev/id`;\n\n/**\n * Default method for building ev charging stations availability request from {@link ChargingStationsAvailabilityParams}\n * @param params The charging availability parameters, with global configuration already merged into them.\n */\nexport const buildEVChargingStationsAvailabilityRequest = (params: ChargingStationsAvailabilityParams): URL => {\n const url = new URL(buildUrlBasePath(params));\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n urlParams.append('id', params.id);\n return url;\n};\n","import { ChargingSpeed } from '@tomtom-org/maps-sdk/core';\n\n/**\n * @ignore\n */\nexport const toChargingSpeed = (powerInKW: number): ChargingSpeed => {\n if (powerInKW < 12) {\n return 'slow';\n } else if (powerInKW < 50) {\n return 'regular';\n } else if (powerInKW < 150) {\n return 'fast';\n }\n return 'ultra-fast';\n};\n","import type {\n ChargingPointAvailability,\n ChargingPointStatus,\n ChargingStation,\n Connector,\n ConnectorAvailability,\n ConnectorCount,\n} from '@tomtom-org/maps-sdk/core';\n\n/**\n * @ignore\n */\nexport const toChargingPointAvailability = (chargingStations: ChargingStation[]): ChargingPointAvailability => {\n const availability: ChargingPointAvailability = { count: 0, statusCounts: {} };\n for (const station of chargingStations) {\n for (const chargingPoint of station.chargingPoints) {\n availability.count++;\n availability.statusCounts[chargingPoint.status] =\n (availability.statusCounts[chargingPoint.status] || 0) + 1;\n }\n }\n return availability;\n};\n\n// Two connectors can be considered equal when they have the same type and power:\nconst areEqual = (connectorA: Connector, connectorB: Connector) =>\n connectorA.type === connectorB.type && connectorA.ratedPowerKW === connectorB.ratedPowerKW;\n\nconst addConnectorCount = (\n connectors: Connector[] | undefined,\n counts: ConnectorCount[], // we are mutating this input\n): void => {\n if (!connectors) {\n // defensive check, sometimes connectors are undefined\n return;\n }\n for (const connector of connectors) {\n const existingCount = counts.find((connectorCount) => areEqual(connector, connectorCount.connector));\n if (existingCount) {\n existingCount.count++;\n } else {\n // new count entry:\n counts.push({ connector, count: 1 });\n }\n }\n};\n\nconst addConnectorCountAndStatus = (\n connectors: Connector[] | undefined,\n status: ChargingPointStatus | undefined,\n availabilities: ConnectorAvailability[], // we are mutating this input\n): void => {\n if (!connectors) {\n // defensive check, sometimes connectors are undefined\n return;\n }\n for (const connector of connectors) {\n const existingAvailability = availabilities.find((connectorAvailability) =>\n areEqual(connector, connectorAvailability.connector),\n );\n if (existingAvailability) {\n existingAvailability.count++;\n if (status) {\n // we're mutating the input object here:\n const statusCounts = existingAvailability.statusCounts;\n existingAvailability.statusCounts[status] = (statusCounts[status] || 0) + 1;\n }\n } else {\n // new availability entry:\n availabilities.push({ connector, count: 1, statusCounts: status ? { [status]: 1 } : {} });\n }\n }\n};\n\n/**\n * @ignore\n */\nexport const toConnectorCounts = (connectors: Connector[]): ConnectorCount[] => {\n const availabilities: ConnectorAvailability[] = [];\n addConnectorCount(connectors, availabilities);\n return availabilities;\n};\n\n/**\n * @ignore\n */\nexport const toConnectorBasedAvailabilities = (chargingStations: ChargingStation[]): ConnectorAvailability[] => {\n const availabilities: ConnectorAvailability[] = [];\n for (const station of chargingStations) {\n for (const chargingPoint of station.chargingPoints) {\n addConnectorCountAndStatus(chargingPoint.connectors, chargingPoint.status, availabilities);\n }\n }\n return availabilities;\n};\n","import type { Moment, OpeningHours, Place, SearchPlaceProps, TimeRange } from '@tomtom-org/maps-sdk/core';\nimport { toPointGeometry } from '@tomtom-org/maps-sdk/core';\nimport { omit } from 'lodash-es';\nimport { toConnectorCounts } from '../ev-charging-stations-availability/connectorAvailability';\nimport { toChargingSpeed } from './ev';\nimport { apiToGeoJSONBBox, latLonAPIToPosition } from './geometry';\nimport type {\n BrandAPI,\n CommonSearchPlaceResultAPI,\n MomentAPI,\n OpeningHoursAPI,\n SummaryAPI,\n} from './types/apiPlacesResponseTypes';\nimport type { SearchSummary } from './types/searchSummary';\n\nconst parseYyyymmddDate = (dateYyyymmdd: string): { year: number; month: number; day: number } => {\n const splitDate = dateYyyymmdd.split('-');\n return {\n year: Number.parseInt(splitDate[0]),\n month: Number.parseInt(splitDate[1]),\n day: Number.parseInt(splitDate[2]),\n };\n};\n\nconst parseMoment = (momentApi: MomentAPI): Moment => {\n const { year, month, day } = parseYyyymmddDate(momentApi.date);\n return {\n dateYYYYMMDD: momentApi.date,\n year,\n month,\n day,\n hour: momentApi.hour,\n minute: momentApi.minute,\n date: new Date(year, month - 1, day, momentApi.hour, momentApi.minute),\n };\n};\n\nconst alwaysOpenInThisPeriod = (timeRanges: TimeRange[]): boolean =>\n timeRanges.length === 1 && timeRanges[0].start.hour === 0 && timeRanges[0].end.hour === 0;\n\n/**\n * @ignore\n */\nexport const parseOpeningHours = (openingHoursApi: OpeningHoursAPI): OpeningHours => {\n const timeRanges = openingHoursApi.timeRanges.map(\n (timeRangeApi): TimeRange => ({\n start: parseMoment(timeRangeApi.startTime),\n end: parseMoment(timeRangeApi.endTime),\n }),\n );\n return {\n mode: openingHoursApi.mode,\n timeRanges,\n alwaysOpenThisPeriod: alwaysOpenInThisPeriod(timeRanges),\n };\n};\n\n/**\n * Shared response parsing between geometry search and place by id service.\n * @ignore\n */\nexport const parseSearchAPIResult = (result: CommonSearchPlaceResultAPI): Place<SearchPlaceProps> => {\n const { position, entryPoints, poi, id, dist, boundingBox, chargingPark, ...rest } = result;\n const connectors = chargingPark?.connectors?.map((connector) => ({\n ...omit(connector, 'connectorType'),\n type: connector.connectorType,\n chargingSpeed: toChargingSpeed(connector.ratedPowerKW),\n }));\n return {\n type: 'Feature',\n geometry: toPointGeometry(latLonAPIToPosition(position)),\n ...(boundingBox && { bbox: apiToGeoJSONBBox(boundingBox) }),\n id,\n properties: {\n ...omit(rest, 'viewport'),\n ...(dist && { distance: dist }),\n ...(entryPoints?.length && {\n entryPoints: entryPoints.map((entrypoint) => ({\n ...entrypoint,\n position: latLonAPIToPosition(entrypoint.position),\n })),\n }),\n ...(connectors?.length && {\n chargingPark: {\n ...chargingPark,\n connectors: toConnectorCounts(connectors),\n },\n }),\n ...(poi && {\n poi: {\n ...omit(poi, 'categorySet', 'openingHours'),\n brands: poi?.brands?.map((brand: BrandAPI) => brand.name) ?? [],\n categoryIds: poi?.categorySet?.map((category) => category.id) ?? [],\n ...(poi?.openingHours && { openingHours: parseOpeningHours(poi?.openingHours) }),\n },\n }),\n },\n };\n};\n\n/**\n * @ignore\n */\nexport const parseSummaryAPI = (summary: SummaryAPI): SearchSummary => {\n const { geoBias, ...rest } = summary;\n\n return {\n ...(geoBias && { geoBias: latLonAPIToPosition(geoBias) }),\n ...rest,\n };\n};\n","import type { ChargingStation, ChargingStationsAvailability } from '@tomtom-org/maps-sdk/core';\nimport { toChargingSpeed } from '../shared/ev';\nimport { parseOpeningHours } from '../shared/searchResultParsing';\nimport { toChargingPointAvailability, toConnectorBasedAvailabilities } from './connectorAvailability';\nimport type { ChargingStationsAvailabilityResponseAPI } from './types/apiTypes';\n\nconst toChargingPointStations = (stations: ChargingStation[]) =>\n stations.map((station) => ({\n ...station,\n chargingPoints: station.chargingPoints.map((chargingPoint) => ({\n ...chargingPoint,\n connectors: chargingPoint.connectors?.map((connector) => ({\n ...connector,\n chargingSpeed: toChargingSpeed(connector.ratedPowerKW),\n })),\n })),\n }));\n\n/**\n * Default method for parsing ev charging stations availability from {@link ChargingStationsAvailability}\n * @param apiResponse\n */\nexport const parseEVChargingStationsAvailabilityResponse = (\n apiResponse: ChargingStationsAvailabilityResponseAPI,\n): ChargingStationsAvailability | undefined => {\n const result = apiResponse.results?.[0];\n return result\n ? {\n id: result.id,\n accessType: result.accessType,\n chargingStations: toChargingPointStations(result.chargingStations),\n chargingPointAvailability: toChargingPointAvailability(result.chargingStations),\n connectorAvailabilities: toConnectorBasedAvailabilities(result.chargingStations),\n ...(result.openingHours && { openingHours: parseOpeningHours(result.openingHours) }),\n }\n : undefined;\n};\n","import type { ChargingStationsAvailability } from '@tomtom-org/maps-sdk/core';\nimport type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { evChargingStationsAvailabilityRequestSchema } from './evChargingStationsAvailabilityRequestSchema';\nimport { parseEVChargingStationsAvailabilityResponseError } from './evChargingStationsAvailabilityResponseErrorParser';\nimport { buildEVChargingStationsAvailabilityRequest } from './requestBuilder';\nimport { parseEVChargingStationsAvailabilityResponse } from './responseParser';\nimport type { ChargingStationsAvailabilityResponseAPI } from './types/apiTypes';\nimport type { ChargingStationsAvailabilityParams } from './types/evChargingStationsAvailabilityParams';\n\n/**\n * EV Charging Stations Availability service template type.\n * @ignore\n */\nexport type EVChargingStationsAvailabilityTemplate = ServiceTemplate<\n ChargingStationsAvailabilityParams,\n URL,\n ChargingStationsAvailabilityResponseAPI,\n ChargingStationsAvailability | undefined\n>;\n\n/**\n * EV Charging Stations Availability service template main implementation.\n * @ignore\n */\nexport const evChargingStationsAvailabilityTemplate: EVChargingStationsAvailabilityTemplate = {\n requestValidation: { schema: evChargingStationsAvailabilityRequestSchema },\n buildRequest: buildEVChargingStationsAvailabilityRequest,\n sendRequest: get,\n parseResponse: parseEVChargingStationsAvailabilityResponse,\n parseResponseError: parseEVChargingStationsAvailabilityResponseError,\n};\n","import type { ParseResponseError } from '../shared';\nimport { SDKServiceError } from '../shared';\n\n/**\n * @ignore\n * @param apiError\n * @param serviceName\n */\nexport const parseEVChargingStationsAvailabilityResponseError: ParseResponseError = (apiError, serviceName) => {\n const errorMessage = apiError.data?.detailedError?.message ?? apiError.message;\n return new SDKServiceError(errorMessage, serviceName, apiError.status);\n};\n","import type { EVChargingStationsAvailabilityTemplate } from './evChargingStationsAvailabilityTemplate';\nimport { evChargingStationsAvailabilityTemplate } from './evChargingStationsAvailabilityTemplate';\nimport { buildEVChargingStationsAvailabilityRequest } from './requestBuilder';\nimport { parseEVChargingStationsAvailabilityResponse } from './responseParser';\n\nconst customize: {\n buildEVChargingStationsAvailabilityRequest: typeof buildEVChargingStationsAvailabilityRequest;\n parseEVChargingStationsAvailabilityResponse: typeof parseEVChargingStationsAvailabilityResponse;\n evChargingStationsAvailabilityTemplate: EVChargingStationsAvailabilityTemplate;\n} = {\n buildEVChargingStationsAvailabilityRequest,\n parseEVChargingStationsAvailabilityResponse,\n evChargingStationsAvailabilityTemplate,\n};\nexport default customize;\n","import { z } from 'zod';\nimport { hasBBoxSchema } from './geometriesSchema';\n\n/**\n * @ignore\n */\nexport const commonGeocodeAndFuzzySearchParamsSchema = z.object({\n typeahead: z.boolean().optional().describe('Enable predictive/autocomplete mode for partial input queries'),\n offset: z\n .number()\n .max(1900)\n .optional()\n .describe('Starting position within result set for pagination (zero-based index)'),\n radiusMeters: z.number().optional().describe('Search radius in meters around the specified position'),\n boundingBox: hasBBoxSchema.optional().describe('Bounding box to constrain search results to a rectangular area'),\n countries: z.array(z.string()).optional().describe('Country codes to restrict search results (ISO 3166-1 alpha-2)'),\n});\n","import { views } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { hasLngLatSchema } from './geometriesSchema';\n\nconst placesParamsMandatory = z.object({\n query: z.string().describe('Search query for places, addresses, or locations'),\n});\n\nconst placesParamsOptional = z.object({\n position: hasLngLatSchema.optional().describe('Geographic position [longitude, latitude] to bias search results'),\n limit: z.number().max(100).optional().describe('Maximum number of results to return (1-100)'),\n extendedPostalCodesFor: z\n .array(z.string())\n .optional()\n .describe('Indexes for which to include extended postal codes in results'),\n mapcodes: z\n .array(z.string())\n .optional()\n .describe('Request mapcode representations for locations (Local, International, Alternative)'),\n view: z.enum(views).optional().describe('Geopolitical view for disputed territories'),\n geographyTypes: z\n .array(z.string())\n .optional()\n .describe('Filter results to specific geography types (Country, Municipality, etc.)'),\n});\n\n/**\n * @ignore\n */\nexport const commonPlacesParamsSchema = placesParamsMandatory.extend(placesParamsOptional.shape);\n","import { commonGeocodeAndFuzzySearchParamsSchema } from '../shared/schema/commonGeocodeAndFuzzySearchParamsSchema';\nimport { commonServiceRequestSchema } from '../shared/schema/commonParamsSchema';\nimport { commonPlacesParamsSchema } from '../shared/schema/commonPlacesParamsSchema';\n\n/**\n * @ignore\n */\nexport const geocodingRequestSchema = commonServiceRequestSchema\n .extend(commonPlacesParamsSchema.shape)\n .extend(commonGeocodeAndFuzzySearchParamsSchema.shape);\n","/**\n * @ignore\n * @param input\n */\nexport const arrayToCSV = (input: unknown | unknown[]): string =>\n !input ? '' : Array.isArray(input) ? input.join(',') : typeof input === 'string' ? input : String(input);\n\n/**\n * Samples, if necessary, the given array to fit within the given max length.\n * * If the array already fits within maxLength, the same array is returned.\n * * The sampling is done by spreading the array points at a constant increment.\n * * The first and last points are always included if array and max lengths are > 1.\n * * The sampling is done with speed in mind, so it's not guaranteed to always fit maxLength. Very often it will be shorter.\n *\n * Use this when needing to quickly simplify an array to fit some max length without caring too much on the lost detail.\n * * If both the array and max length are long enough, the loss of detail won't likely be an issue.\n * @ignore\n */\nexport const sampleWithinMaxLength = <T>(array: T[], maxLength: number): T[] => {\n const length = array.length;\n if (length <= maxLength) {\n return array;\n }\n\n const sampledArray = [];\n let i;\n const increment = Math.ceil(length / maxLength);\n for (i = 0; i < length; i += increment) {\n sampledArray.push(array[i]);\n }\n // ensuring the last point is always added:\n if (maxLength > 1 && i >= length - increment) {\n if (sampledArray.length < maxLength) {\n sampledArray.push(array[length - 1]);\n } else {\n sampledArray[sampledArray.length - 1] = array[length - 1];\n }\n }\n\n return sampledArray;\n};\n","import { bboxFromGeoJSON } from '@tomtom-org/maps-sdk/core';\nimport { isNil } from 'lodash-es';\nimport { arrayToCSV } from '../shared/arrays';\nimport { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport { appendCommonParams, appendLatLonParamsFromPosition } from '../shared/request/requestBuildingUtils';\nimport type { GeocodingParams } from './types/geocodingParams';\n\nconst buildUrlBasePath = (params: GeocodingParams): string =>\n params.customServiceBaseURL || `${params.commonBaseURL}${PLACES_URL_PATH}/geocode`;\n\n/**\n * Default method for building geocoding request from {@link GeocodingParams}\n * @param params The geocoding parameters, with global configuration already merged into them.\n */\nexport const buildGeocodingRequest = (params: GeocodingParams): URL => {\n const url = new URL(`${buildUrlBasePath(params)}/${params.query}.json`);\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n // geocoding specific parameters:\n params.typeahead && urlParams.append('typeahead', String(params.typeahead));\n !isNil(params.limit) && urlParams.append('limit', String(params.limit));\n !isNil(params.offset) && urlParams.append('ofs', String(params.offset));\n appendLatLonParamsFromPosition(urlParams, params.position);\n params.countries && urlParams.append('countrySet', arrayToCSV(params.countries));\n !isNil(params.radiusMeters) && urlParams.append('radius', String(params.radiusMeters));\n const bbox = params.boundingBox && bboxFromGeoJSON(params.boundingBox);\n if (bbox) {\n urlParams.append('topLeft', arrayToCSV([bbox[3], bbox[0]]));\n urlParams.append('btmRight', arrayToCSV([bbox[1], bbox[2]]));\n }\n params.extendedPostalCodesFor &&\n urlParams.append('extendedPostalCodesFor', arrayToCSV(params.extendedPostalCodesFor));\n params.mapcodes && urlParams.append('mapcodes', arrayToCSV(params.mapcodes));\n params.view && urlParams.append('view', params.view);\n params.geographyTypes && urlParams.append('entityTypeSet', arrayToCSV(params.geographyTypes));\n return url;\n};\n","import type { GeographyType, Place } from '@tomtom-org/maps-sdk/core';\nimport { bboxFromGeoJSON, bboxOnlyIfWithArea, toPointGeometry } from '@tomtom-org/maps-sdk/core';\nimport { omit } from 'lodash-es';\nimport { apiToGeoJSONBBox, latLonAPIToPosition } from '../shared/geometry';\nimport type { GeocodingResponseAPI, GeocodingResultAPI } from './types/apiTypes';\nimport type { GeocodingProps, GeocodingResponse } from './types/geocodingResponse';\n\nconst parseApiResult = (result: GeocodingResultAPI): Place<GeocodingProps> => {\n const { position, boundingBox, dist, entryPoints, addressRanges, entityType, id, ...rest } = result;\n\n return {\n type: 'Feature',\n geometry: toPointGeometry(latLonAPIToPosition(position)),\n ...(boundingBox && { bbox: apiToGeoJSONBBox(boundingBox) }),\n id,\n properties: {\n ...omit(rest, 'viewport'),\n ...(dist && { distance: dist }),\n ...(entityType && { geographyType: entityType.split(',') as GeographyType[] }),\n ...(entryPoints && {\n entryPoints: entryPoints.map((entrypoint) => ({\n ...entrypoint,\n position: latLonAPIToPosition(entrypoint.position),\n })),\n }),\n ...(addressRanges && {\n addressRanges: {\n ...addressRanges,\n from: latLonAPIToPosition(addressRanges.from),\n to: latLonAPIToPosition(addressRanges.to),\n },\n }),\n },\n };\n};\n\n/**\n * Default method for parsing geocoding request from {@link GeocodingResponse}\n * @param apiResponse\n */\nexport const parseGeocodingResponse = (apiResponse: GeocodingResponseAPI): GeocodingResponse => {\n const results = apiResponse.results;\n const features = results.map(parseApiResult);\n const bbox = bboxOnlyIfWithArea(bboxFromGeoJSON(features));\n return {\n type: 'FeatureCollection',\n features,\n ...(bbox && { bbox }),\n };\n};\n","import type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { geocodingRequestSchema } from './geocodingRequestSchema';\nimport { buildGeocodingRequest } from './requestBuilder';\nimport { parseGeocodingResponse } from './responseParser';\nimport type { GeocodingResponseAPI } from './types/apiTypes';\nimport type { GeocodingParams } from './types/geocodingParams';\nimport type { GeocodingResponse } from './types/geocodingResponse';\n\n/**\n * Geocoding service template type.\n * @ignore\n */\nexport type GeocodingTemplate = ServiceTemplate<GeocodingParams, URL, GeocodingResponseAPI, GeocodingResponse>;\n\n/**\n * Geocoding service template main implementation.\n * @ignore\n */\nexport const geocodingTemplate: GeocodingTemplate = {\n requestValidation: { schema: geocodingRequestSchema },\n buildRequest: buildGeocodingRequest,\n sendRequest: get,\n parseResponse: parseGeocodingResponse,\n};\n","import type { GeocodingTemplate } from './geocodingTemplate';\nimport { geocodingTemplate } from './geocodingTemplate';\nimport { buildGeocodingRequest } from './requestBuilder';\nimport { parseGeocodingResponse } from './responseParser';\n\nconst customize: {\n buildGeocodingRequest: typeof buildGeocodingRequest;\n parseGeocodingResponse: typeof parseGeocodingResponse;\n geocodingTemplate: GeocodingTemplate;\n} = {\n buildGeocodingRequest,\n parseGeocodingResponse,\n geocodingTemplate,\n};\nexport default customize;\n","import { z } from 'zod';\nimport { featureCollectionSchema, featureSchema } from '../shared/schema/geometriesSchema';\n\nconst geometryDataRequestMandatory = z.object({\n geometries: z\n .union([\n featureCollectionSchema,\n z\n .array(z.union([z.string(), featureSchema]))\n .min(1)\n .max(20),\n ])\n .describe('GeoJSON FeatureCollection or array of geometry IDs/Features (max 20)'),\n});\n\nconst geometryDataRequestOptional = z.object({\n zoom: z.number().min(0).max(22).optional().describe('Zoom level for geometry data simplification (0-22)'),\n});\n\nexport const geometryDataRequestSchema = geometryDataRequestMandatory.extend(geometryDataRequestOptional.shape);\n","import type { Place, Places } from '@tomtom-org/maps-sdk/core';\nimport { arrayToCSV } from '../shared/arrays';\nimport { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport { appendOptionalParam } from '../shared/request/requestBuildingUtils';\nimport type { GeometriesInput, GeometryParams } from './types/geometryDataParams';\n\nconst buildUrlBasePath = (params: GeometryParams): string =>\n params.customServiceBaseURL || `${params.commonBaseURL}${PLACES_URL_PATH}/additionalData.json`;\n\nconst getGeometryIDs = (placesArray: Place[]): string[] =>\n placesArray.map((place) => place.properties.dataSources?.geometry?.id as string).filter((id) => id);\n\n// (@see geometryDataRequestSchema)\nconst appendGeometries = (urlParams: URLSearchParams, geometries: GeometriesInput | Places | Place[]): void => {\n let geometryIDs: string[];\n\n if (Array.isArray(geometries)) {\n // (assuming min and max length already validated)\n if (typeof geometries[0] === 'string') {\n geometryIDs = geometries as string[];\n } else {\n geometryIDs = getGeometryIDs(geometries as Place[]);\n }\n } else {\n // (assuming already validated as FeatureCollection)\n geometryIDs = getGeometryIDs(geometries.features);\n }\n\n urlParams.append('geometries', arrayToCSV(geometryIDs));\n};\n\n/**\n * Default function for building a geometry data request from {@link GeometryDataParams}\n * @param params The geometry data parameters, with global configuration already merged into them.\n */\nexport const buildGeometryDataRequest = (params: GeometryParams): URL => {\n const url = new URL(buildUrlBasePath(params));\n const urlParams = url.searchParams;\n // (no language in this service)\n urlParams.append('apiVersion', String(params.apiVersion));\n urlParams.append('key', params.apiKey as string);\n appendGeometries(urlParams, params.geometries);\n appendOptionalParam(urlParams, 'geometriesZoom', params.zoom);\n return url;\n};\n","import { bboxFromGeoJSON, generateId, PolygonFeature, PolygonFeatures } from '@tomtom-org/maps-sdk/core';\nimport type { GeometryDataResponseAPI } from './types/apiTypes';\n\n/**\n * Default geometry data API response parsing.\n * * The API response consists of an array, with a FeatureCollection (with only one feature) for each geometry.\n * * The parsed response consists of a fully-GeoJSON-compatible FeatureCollection with a Feature for each geometry.\n * * Each geometry ID is included in each GeoJSON feature \"id\" field.\n * @param apiResponse\n */\nexport const parseGeometryDataResponse = (apiResponse: GeometryDataResponseAPI): PolygonFeatures => {\n const features = apiResponse.additionalData\n .flatMap((data) =>\n (data.geometryData as PolygonFeatures)?.features.map((feature) => ({\n ...feature,\n id: feature.id ?? generateId(),\n bbox: bboxFromGeoJSON(feature.geometry),\n })),\n )\n .filter((feature) => feature) as PolygonFeature[];\n return {\n type: 'FeatureCollection',\n bbox: bboxFromGeoJSON(features),\n features,\n };\n};\n","import type { PolygonFeatures } from '@tomtom-org/maps-sdk/core';\nimport type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { geometryDataRequestSchema } from './geometryDataRequestSchema';\nimport { buildGeometryDataRequest } from './requestBuilder';\nimport { parseGeometryDataResponse } from './responseParser';\nimport type { GeometryDataResponseAPI } from './types/apiTypes';\nimport type { GeometryParams } from './types/geometryDataParams';\n\n/**\n * @ignore\n */\nexport type GeometryDataTemplate = ServiceTemplate<GeometryParams, URL, GeometryDataResponseAPI, PolygonFeatures>;\n\n/**\n * @ignore\n */\nexport const geometryDataTemplate: GeometryDataTemplate = {\n requestValidation: { schema: geometryDataRequestSchema },\n buildRequest: buildGeometryDataRequest,\n sendRequest: get,\n parseResponse: parseGeometryDataResponse,\n};\n","import type { GeometryDataTemplate } from './geometryDataTemplate';\nimport { geometryDataTemplate } from './geometryDataTemplate';\nimport { buildGeometryDataRequest } from './requestBuilder';\nimport { parseGeometryDataResponse } from './responseParser';\n\nconst customize: {\n buildGeometryDataRequest: typeof buildGeometryDataRequest;\n parseGeometryDataResponse: typeof parseGeometryDataResponse;\n geometryDataTemplate: GeometryDataTemplate;\n} = {\n buildGeometryDataRequest,\n parseGeometryDataResponse,\n geometryDataTemplate,\n};\nexport default customize;\n","import { poiCategoriesToID } from '@tomtom-org/maps-sdk/core';\nimport { type ZodObject, z } from 'zod';\nimport { commonPlacesParamsSchema } from '../shared/schema/commonPlacesParamsSchema';\n\nconst poiCategoriesToIdZodObject = z.object(poiCategoriesToID) as unknown as ZodObject<any>;\n\nconst searchExtraParamsOptional = z.object({\n indexes: z.array(z.string()).optional().describe('Search indexes to query (Geo, PAD, Addr, Str, XStr, POI)'),\n poiCategories: z\n .array(z.union([z.number(), z.keyof(poiCategoriesToIdZodObject)]))\n .optional()\n .describe('Filter results to specific POI categories'),\n poiBrands: z.array(z.string()).optional().describe('Filter results to specific POI brands'),\n connectors: z.array(z.string()).optional().describe('Filter EV charging stations by connector types'),\n fuelTypes: z.array(z.string()).optional().describe('Filter fuel stations by available fuel types'),\n openingHours: z.string().optional().describe('Request opening hours information for POIs'),\n timeZone: z.string().optional().describe('Request timezone information for POI locations (iana)'),\n relatedPois: z.string().optional().describe('Related POI inclusion mode (off, child, parent, all)'),\n minPowerKW: z.number().optional().describe('Minimum charging power in kilowatts for EV charging stations'),\n maxPowerKW: z.number().optional().describe('Maximum charging power in kilowatts for EV charging stations'),\n minFuzzyLevel: z.number().optional().describe('Minimum fuzzy matching level (1-4)'),\n mixFuzzyLevel: z.number().optional().describe('Maximum fuzzy matching level (1-4)'),\n});\n\n/**\n * @ignore\n */\nexport const commonSearchParamsSchema = commonPlacesParamsSchema.extend(searchExtraParamsOptional.shape);\n","import { z } from 'zod';\nimport { commonSearchParamsSchema } from '../search/commonSearchParamsSchema';\nimport { featureCollectionSchema, geometrySchema } from '../shared/schema/geometriesSchema';\n\nconst geometrySearchRequestMandatory = z.object({\n geometries: z\n .array(z.union([featureCollectionSchema, geometrySchema]))\n .describe('Array of GeoJSON geometries or FeatureCollections to search within'),\n});\n\n/**\n * @ignore\n */\nexport const geometrySearchRequestSchema = commonSearchParamsSchema.extend(geometrySearchRequestMandatory.shape);\n","import { bboxFromCoordsArray } from '@tomtom-org/maps-sdk/core';\nimport type { MultiPolygon, Position } from 'geojson';\nimport type { PostObject } from '../shared';\nimport { sampleWithinMaxLength } from '../shared/arrays';\nimport { positionToCSVLatLon } from '../shared/geometry';\nimport { appendCommonSearchParams, PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport type { GeometryAPI, GeometrySearchParams, GeometrySearchPayloadAPI, SearchGeometryInput } from './types';\n\nconst findFiftyLargestPolygons = (searchGeometry: MultiPolygon): Position[][][] => {\n // we calculate the size of each polygon based on bounding box (simplified)\n // we put it into a map for easy sorting\n // we sort the map by using size and keep only 50 largest polygons\n let polygonSizeMap = new Map<Position[][], number>();\n searchGeometry.coordinates.forEach((polygon) => {\n const bboxOfPolygon = bboxFromCoordsArray(polygon[0]);\n if (bboxOfPolygon) {\n const polygonSize = Math.abs((bboxOfPolygon[2] - bboxOfPolygon[0]) * (bboxOfPolygon[3] - bboxOfPolygon[1]));\n polygonSizeMap.set(polygon, polygonSize);\n }\n });\n polygonSizeMap = new Map([...polygonSizeMap.entries()].sort((a, b) => b[1] - a[1]).splice(0, 50));\n return [...polygonSizeMap.keys()];\n};\n\nconst sdkGeometryToApiGeometries = (searchGeometry: SearchGeometryInput): GeometryAPI[] => {\n switch (searchGeometry.type) {\n case 'Circle':\n return [\n {\n type: 'CIRCLE',\n radius: searchGeometry.radius,\n position: positionToCSVLatLon(searchGeometry.coordinates),\n },\n ];\n case 'Polygon':\n return [\n {\n type: 'POLYGON',\n vertices: sampleWithinMaxLength(searchGeometry.coordinates[0], 50).map((coord) =>\n positionToCSVLatLon(coord),\n ),\n },\n ];\n case 'MultiPolygon': {\n if (searchGeometry.coordinates.length > 50) {\n // we have too many polygons for the service to work\n return findFiftyLargestPolygons(searchGeometry).flatMap((polygonCoords) =>\n sdkGeometryToApiGeometries({ type: 'Polygon', coordinates: polygonCoords }),\n );\n }\n return searchGeometry.coordinates.flatMap((polygonCoords) =>\n sdkGeometryToApiGeometries({ type: 'Polygon', coordinates: polygonCoords }),\n );\n }\n case 'FeatureCollection':\n return searchGeometry.features.flatMap((feature) => sdkGeometryToApiGeometries(feature.geometry));\n default:\n // @ts-ignore\n throw new Error(`Type ${(searchGeometry as unknown).type} is not supported`);\n }\n};\n\nconst buildUrlBasePath = (mergedOptions: GeometrySearchParams): string =>\n mergedOptions.customServiceBaseURL ??\n `${mergedOptions.commonBaseURL}${PLACES_URL_PATH}/geometrySearch/${mergedOptions.query}.json`;\n\n/**\n * Default function for building a geometry search request from {@link GeometrySearchParams}\n * @param params The geometry search parameters, with global configuration already merged into them.\n */\nexport const buildGeometrySearchRequest = (params: GeometrySearchParams): PostObject<GeometrySearchPayloadAPI> => {\n const url = new URL(`${buildUrlBasePath(params)}`);\n appendCommonSearchParams(url, params);\n\n return {\n url,\n data: {\n geometryList: params.geometries.flatMap(sdkGeometryToApiGeometries),\n },\n };\n};\n","import { bboxFromGeoJSON, bboxOnlyIfWithArea } from '@tomtom-org/maps-sdk/core';\nimport { parseSearchAPIResult, parseSummaryAPI } from '../shared/searchResultParsing';\nimport type { GeometrySearchResponse, GeometrySearchResponseAPI } from './types';\n\n/**\n * Default function to parse a geometry search response.\n * @param apiResponse The API response.\n */\nexport const parseGeometrySearchResponse = (apiResponse: GeometrySearchResponseAPI): GeometrySearchResponse => {\n const features = apiResponse.results.map(parseSearchAPIResult);\n const bbox = bboxOnlyIfWithArea(bboxFromGeoJSON(features));\n return {\n type: 'FeatureCollection',\n properties: {\n ...parseSummaryAPI(apiResponse.summary),\n },\n features,\n ...(bbox && { bbox }),\n };\n};\n","import type { ServiceTemplate } from '../shared';\nimport { post } from '../shared/fetch';\nimport { geometrySearchRequestSchema } from './geometrySearchRequestSchema';\nimport { buildGeometrySearchRequest } from './requestBuilder';\nimport { parseGeometrySearchResponse } from './responseParser';\nimport type {\n GeometrySearchParams,\n GeometrySearchRequestAPI,\n GeometrySearchResponse,\n GeometrySearchResponseAPI,\n} from './types';\n\n/**\n * Geometry search service template type.\n */\nexport type GeometrySearchTemplate = ServiceTemplate<\n GeometrySearchParams,\n GeometrySearchRequestAPI,\n GeometrySearchResponseAPI,\n GeometrySearchResponse\n>;\n\n/**\n * Geometry search service template main implementation.\n */\nexport const geometrySearchTemplate: GeometrySearchTemplate = {\n requestValidation: { schema: geometrySearchRequestSchema },\n buildRequest: buildGeometrySearchRequest,\n sendRequest: post,\n parseResponse: parseGeometrySearchResponse,\n};\n","import { callService } from '../shared/serviceTemplate';\nimport type { GeometrySearchTemplate } from './geometrySearchTemplate';\nimport { geometrySearchTemplate } from './geometrySearchTemplate';\nimport type { GeometrySearchParams, GeometrySearchResponse } from './types';\n\n/**\n * Search for places within specific geographic boundaries.\n *\n * The Geometry Search service finds places that fall within one or more defined areas,\n * such as polygons, circles, or corridors. This is essential for location-based filtering\n * and spatial queries where you need results constrained to specific regions.\n *\n * @remarks\n * Key features:\n * - **Area-based search**: Find places within polygons, circles, or along routes\n * - **Multiple geometries**: Search across several areas simultaneously\n * - **Precise boundaries**: Only returns results within the specified areas\n * - **Combined with text**: Filter by query text within the geometric boundaries\n * - **Category filtering**: Narrow results by POI categories\n *\n * Common use cases:\n * - **Route-based search**: \"Find gas stations along my route\"\n * - **Area filtering**: \"Restaurants within this neighborhood polygon\"\n * - **Corridor search**: \"Hotels within 5km of the highway\"\n * - **Service areas**: \"Stores within our delivery zone\"\n * - **Geofencing**: Places within administrative or custom boundaries\n *\n * @param params Geometry search parameters including geometries and optional query\n * @param customTemplate Advanced customization for request/response handling\n *\n * @returns Promise resolving to places within the specified geometries\n *\n * @example\n * ```typescript\n * // Search within a polygon (neighborhood boundaries)\n * const inArea = await geometrySearch({\n * key: 'your-api-key',\n * query: 'coffee shop',\n * geometries: [{\n * type: 'Polygon',\n * coordinates: [[\n * [4.88, 52.36],\n * [4.90, 52.36],\n * [4.90, 52.38],\n * [4.88, 52.38],\n * [4.88, 52.36]\n * ]]\n * }]\n * });\n *\n * // Find POIs along a route corridor\n * const alongRoute = await geometrySearch({\n * key: 'your-api-key',\n * query: 'gas station',\n * geometries: [routeLineString], // From calculateRoute result\n * geometryList: [{\n * position: 0,\n * radius: 5000 // 5km corridor along route\n * }]\n * });\n *\n * // Search multiple areas at once\n * const multiArea = await geometrySearch({\n * key: 'your-api-key',\n * query: 'pharmacy',\n * geometries: [polygonA, polygonB, polygonC],\n * limit: 20\n * });\n *\n * // Category search within geometry\n * const restaurants = await geometrySearch({\n * key: 'your-api-key',\n * categorySet: [7315], // Restaurant category\n * geometries: [cityBoundary]\n * });\n * ```\n *\n * @see [Geometry Search API Documentation](https://docs.tomtom.com/search-api/documentation/search-service/geometry-search)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Search Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/search)\n *\n * @ignore (exposed via 'search')\n */\nexport const geometrySearch = async (\n params: GeometrySearchParams,\n customTemplate?: Partial<GeometrySearchTemplate>,\n): Promise<GeometrySearchResponse> =>\n callService(params, { ...geometrySearchTemplate, ...customTemplate }, 'GeometrySearch');\n\nexport default geometrySearch;\n","import { geometrySearch } from './geometrySearch';\nimport type { GeometrySearchTemplate } from './geometrySearchTemplate';\nimport { geometrySearchTemplate } from './geometrySearchTemplate';\nimport { buildGeometrySearchRequest } from './requestBuilder';\nimport { parseGeometrySearchResponse } from './responseParser';\n\nconst customize: {\n geometrySearch: typeof geometrySearch;\n buildGeometrySearchRequest: typeof buildGeometrySearchRequest;\n parseGeometrySearchResponse: typeof parseGeometrySearchResponse;\n geometrySearchTemplate: GeometrySearchTemplate;\n} = {\n geometrySearch,\n buildGeometrySearchRequest,\n parseGeometrySearchResponse,\n geometrySearchTemplate,\n};\nexport default customize;\n","import { views } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\n\nconst placeByIdRequestMandatory = z.object({\n entityId: z.string().describe('Unique identifier of the place/entity to retrieve'),\n});\n\nconst placeByIdRequestOptional = z.object({\n mapcodes: z.array(z.string()).optional().describe('Request mapcode representations for location'),\n view: z.enum(views).optional().describe('Geopolitical view for disputed territories'),\n openingHours: z.string().optional().describe('Request opening hours information for the place'),\n timeZone: z.string().optional().describe('Request timezone information for the place location'),\n relatedPois: z.string().optional().describe('Related POI inclusion mode (off, child, parent, all)'),\n});\n\n/**\n * @ignore\n */\nexport const placeByIdRequestSchema = placeByIdRequestMandatory.extend(placeByIdRequestOptional.shape);\n","import type { CommonServiceParams } from '../shared';\nimport { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport {\n appendByJoiningParamValue,\n appendCommonParams,\n appendOptionalParam,\n} from '../shared/request/requestBuildingUtils';\nimport type { PlaceByIdParams } from './types';\n\nconst buildUrlBasePath = (params: CommonServiceParams): string =>\n params.customServiceBaseURL || `${params.commonBaseURL}${PLACES_URL_PATH}/place.json`;\n\n/**\n * Default method for building place by id request from {@link PlaceByIdParams}\n * @param params The place by id parameters, with global configuration already merged into them.\n */\nexport const buildPlaceByIdRequest = (params: PlaceByIdParams): URL => {\n const url = new URL(`${buildUrlBasePath(params)}`);\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n appendOptionalParam(urlParams, 'entityId', params.entityId);\n appendByJoiningParamValue(urlParams, 'mapcodes', params.mapcodes);\n appendOptionalParam(urlParams, 'view', params.view);\n appendOptionalParam(urlParams, 'openingHours', params.openingHours);\n appendOptionalParam(urlParams, 'timeZone', params.timeZone);\n appendOptionalParam(urlParams, 'relatedPois', params.relatedPois);\n return url;\n};\n","import { parseSearchAPIResult } from '../shared/searchResultParsing';\nimport type { PlaceByIdResponse, PlaceByIdResponseAPI } from './types';\n\n/**\n * Default method for parsing place by id response.\n * @param apiResponse The place by id response.\n */\nexport const parsePlaceByIdResponse = (apiResponse: PlaceByIdResponseAPI): PlaceByIdResponse =>\n apiResponse.results?.length ? parseSearchAPIResult(apiResponse.results[0]) : undefined;\n","import type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { placeByIdRequestSchema } from './placeByIdSchema';\nimport { buildPlaceByIdRequest } from './requestBuilder';\nimport { parsePlaceByIdResponse } from './responseParser';\nimport type { PlaceByIdParams, PlaceByIdResponse, PlaceByIdResponseAPI } from './types';\n\n/**\n * Place By Is template type.\n * @ignore\n */\nexport type PlaceByIdTemplate = ServiceTemplate<PlaceByIdParams, URL, PlaceByIdResponseAPI, PlaceByIdResponse>;\n\n/**\n * Place By Id template main implementation.\n * @ignore\n */\nexport const placeByIdTemplate: PlaceByIdTemplate = {\n requestValidation: { schema: placeByIdRequestSchema },\n buildRequest: buildPlaceByIdRequest,\n sendRequest: get,\n parseResponse: parsePlaceByIdResponse,\n};\n","import type { PlaceByIdTemplate } from './placeByIdTemplate';\nimport { placeByIdTemplate } from './placeByIdTemplate';\nimport { buildPlaceByIdRequest } from './requestBuilder';\nimport { parsePlaceByIdResponse } from './responseParser';\n\nconst customize: {\n buildPlaceByIdRequest: typeof buildPlaceByIdRequest;\n parsePlaceByIdResponse: typeof parsePlaceByIdResponse;\n placeByIdTemplate: PlaceByIdTemplate;\n} = {\n buildPlaceByIdRequest,\n parsePlaceByIdResponse,\n placeByIdTemplate,\n};\nexport default customize;\n","import type { ParseResponseError } from '../shared';\nimport { SDKServiceError } from '../shared';\nimport type { RoutingAPIResponseError } from '../shared/types/apiResponseErrorTypes';\n\n/**\n * @ignore\n * @param apiError\n * @param serviceName\n */\nexport const parseRoutingResponseError: ParseResponseError<RoutingAPIResponseError> = (apiError, serviceName) => {\n const { data, message, status } = apiError;\n const errorMessage = data?.error?.description ?? data?.detailedError?.message ?? message;\n return new SDKServiceError(errorMessage, serviceName, status);\n};\n","import { currentTypes, plugTypes } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { loadTypes } from '../types/vehicleRestrictionParams';\n\n// Common validation schemas\nconst positiveNumber = z.number().positive();\nconst nonNegativeNumber = z.number().min(0);\nconst percentageNumber = z.number().min(0).max(100);\n\n// Common optional schemas\nconst optionalPositiveNumber = positiveNumber.optional();\nconst optionalNonNegativeNumber = nonNegativeNumber.optional();\nconst optionalNormalizedNumber = z.number().min(0).max(1).optional();\n\n// Speed to consumption rate schema\nconst speedToConsumptionRateSchema = z.object({\n speedKMH: z.number().describe('Speed in kilometers per hour'),\n consumptionUnitsPer100KM: z.number().describe('Consumption rate per 100 kilometers'),\n});\n\n// Efficiency schema for consumption models\nconst efficiencySchema = z\n .object({\n acceleration: optionalNormalizedNumber.describe('Acceleration efficiency factor (0-1)'),\n deceleration: optionalNormalizedNumber.describe('Deceleration efficiency factor (0-1)'),\n uphill: optionalNormalizedNumber.describe('Uphill efficiency factor (0-1)'),\n downhill: optionalNormalizedNumber.describe('Downhill efficiency factor (0-1)'),\n })\n .optional();\n\n// Base consumption model schema\nconst baseConsumptionModelSchema = {\n efficiency: efficiencySchema,\n};\n\n// Consumption array validation\nconst speedConsumptionArray = z.array(speedToConsumptionRateSchema).min(1).max(25);\n\n// Combustion consumption model schema\nconst combustionConsumptionModelSchema = z.object({\n ...baseConsumptionModelSchema,\n speedsToConsumptionsLiters: speedConsumptionArray.describe(\n 'Array of speed-to-fuel-consumption mappings in liters per 100km',\n ),\n auxiliaryPowerInLitersPerHour: optionalNonNegativeNumber.describe('Auxiliary power consumption in liters per hour'),\n fuelEnergyDensityInMJoulesPerLiter: z\n .number()\n .min(1)\n .optional()\n .describe('Fuel energy density in megajoules per liter'),\n});\n\n// Electric consumption model schema\nconst electricConsumptionModelSchema = z.object({\n ...baseConsumptionModelSchema,\n speedsToConsumptionsKWH: speedConsumptionArray.describe(\n 'Array of speed-to-energy-consumption mappings in kWh per 100km',\n ),\n auxiliaryPowerInkW: optionalNonNegativeNumber.describe('Auxiliary power consumption in kilowatts'),\n consumptionInKWHPerKMAltitudeGain: z\n .number()\n .max(500)\n .optional()\n .describe('Energy consumption per kilometer of altitude gain in kWh'),\n recuperationInKWHPerKMAltitudeLoss: optionalNonNegativeNumber.describe(\n 'Energy recuperation per kilometer of altitude loss in kWh',\n ),\n});\n\n// Charging connector schema\nconst chargingConnectorSchema = z.object({\n currentType: z.enum(currentTypes).describe('Type of electrical current (AC or DC)'),\n plugTypes: z.array(z.enum(plugTypes)).min(1).describe('Compatible plug/connector types'),\n efficiency: optionalNormalizedNumber.describe('Charging efficiency factor (0-1)'),\n baseLoadInkW: optionalNonNegativeNumber.describe('Base load in kilowatts'),\n maxPowerInkW: optionalNonNegativeNumber.describe('Maximum charging power in kilowatts'),\n maxVoltageInV: optionalNonNegativeNumber.describe('Maximum voltage in volts'),\n maxCurrentInA: optionalNonNegativeNumber.describe('Maximum current in amperes'),\n voltageRange: z\n .object({\n minVoltageInV: optionalNonNegativeNumber.describe('Minimum voltage in volts'),\n maxVoltageInV: z.number().optional().describe('Maximum voltage in volts'),\n })\n .optional()\n .describe('Acceptable voltage range'),\n});\n\n// Battery curve schema\nconst batteryCurveSchema = z.object({\n stateOfChargeInkWh: nonNegativeNumber.describe('State of charge in kilowatt-hours'),\n maxPowerInkW: positiveNumber.describe('Maximum charging power at this state of charge in kilowatts'),\n});\n\n// Charging model schema\nconst chargingModelSchema = z.object({\n maxChargeKWH: positiveNumber.describe('Maximum battery capacity in kilowatt-hours'),\n batteryCurve: z\n .array(batteryCurveSchema)\n .max(20)\n .optional()\n .describe('Battery charging curve with up to 20 data points'),\n chargingConnectors: z\n .array(chargingConnectorSchema)\n .min(1)\n .optional()\n .describe('Available charging connectors on the vehicle'),\n chargingTimeOffsetInSec: optionalNonNegativeNumber.describe('Time offset for charging start in seconds'),\n});\n\n// Engine model schemas\nconst combustionEngineModelSchema = z.object({\n consumption: combustionConsumptionModelSchema.describe('Fuel consumption model for combustion engine'),\n});\nconst electricEngineModelSchema = z.object({\n consumption: electricConsumptionModelSchema.describe('Energy consumption model for electric engine'),\n charging: chargingModelSchema.optional().describe('Battery and charging specifications'),\n});\n\n// Vehicle dimensions schema\nconst vehicleDimensionsSchema = z\n .object({\n lengthMeters: optionalPositiveNumber.describe('Vehicle length in meters'),\n widthMeters: optionalPositiveNumber.describe('Vehicle width in meters'),\n heightMeters: optionalPositiveNumber.describe('Vehicle height in meters'),\n weightKG: optionalPositiveNumber.describe('Vehicle weight in kilograms'),\n axleWeightKG: optionalPositiveNumber.describe('Vehicle axle weight in kilograms'),\n })\n .optional();\n\n// Vehicle model schemas\nconst predefinedVehicleModelSchema = z.object({\n variantId: z.string().describe('Predefined vehicle variant identifier'),\n});\nconst explicitVehicleModelSchema = z.object({\n dimensions: vehicleDimensionsSchema.describe('Physical dimensions and weight of the vehicle'),\n engine: z\n .union([combustionEngineModelSchema, electricEngineModelSchema])\n .optional()\n .describe('Engine type and consumption characteristics'),\n});\nconst vehicleModelSchema = z.union([predefinedVehicleModelSchema, explicitVehicleModelSchema]).optional();\n\n// Vehicle state schemas\nconst genericVehicleStateSchema = z.object({\n heading: z.number().min(0).max(360).optional().describe('Current vehicle heading in degrees (0-360)'),\n});\n\nconst combustionVehicleStateSchema = genericVehicleStateSchema.extend({\n currentFuelInLiters: nonNegativeNumber.describe('Current fuel level in liters'),\n});\n\nconst electricVehicleStateByPercentageSchema = genericVehicleStateSchema.extend({\n currentChargePCT: percentageNumber.describe('Current battery charge as percentage (0-100)'),\n});\n\nconst electricVehicleStateByKwhSchema = genericVehicleStateSchema.extend({\n currentChargeInkWh: nonNegativeNumber.describe('Current battery charge in kilowatt-hours'),\n});\n\nconst electricVehicleStateSchema = z.union([electricVehicleStateByPercentageSchema, electricVehicleStateByKwhSchema]);\n\n// Charging preferences schemas\nconst chargingPreferencesPCTSchema = z.object({\n minChargeAtDestinationPCT: percentageNumber.describe(\n 'Minimum battery charge percentage required at destination (0-100)',\n ),\n minChargeAtChargingStopsPCT: z\n .number()\n .min(0)\n .max(50)\n .describe('Minimum battery charge percentage at charging stops (0-50)'),\n});\n\nconst chargingPreferencesKWHSchema = z.object({\n minChargeAtDestinationInkWh: nonNegativeNumber.describe('Minimum battery charge in kWh required at destination'),\n minChargeAtChargingStopsInkWh: nonNegativeNumber.describe('Minimum battery charge in kWh at charging stops'),\n});\n\nconst chargingPreferencesSchema = z.union([chargingPreferencesPCTSchema, chargingPreferencesKWHSchema]);\nconst electricVehiclePreferencesSchema = z.object({\n chargingPreferences: chargingPreferencesSchema\n .optional()\n .describe('Preferences for charging stops along the route'),\n});\n\n// Vehicle restrictions schema\nconst vehicleRestrictionsSchema = z\n .object({\n loadTypes: z\n .array(z.enum(loadTypes))\n .optional()\n .describe('Types of hazardous or restricted loads being carried'),\n maxSpeedKMH: z\n .number()\n .min(0)\n .max(250)\n .optional()\n .describe('Maximum vehicle speed in kilometers per hour (0-250)'),\n adrCode: z\n .enum(['B', 'C', 'D', 'E'])\n .optional()\n .describe('ADR tunnel restriction code for hazardous materials'),\n commercial: z.boolean().optional().describe('Whether the vehicle is used for commercial purposes'),\n })\n .optional();\n\n// Base vehicle parameters schema\nconst baseVehicleParamsSchema = {\n model: vehicleModelSchema,\n restrictions: vehicleRestrictionsSchema,\n};\n\n// Vehicle parameters schemas\nconst genericVehicleParamsSchema = z.object({\n ...baseVehicleParamsSchema,\n engineType: z.undefined(),\n state: genericVehicleStateSchema.optional().describe('Current state of the vehicle'),\n preferences: z.object({}).optional().describe('Vehicle preferences'),\n});\n\nconst combustionVehicleParamsSchema = z.object({\n ...baseVehicleParamsSchema,\n engineType: z.literal('combustion').describe('Combustion engine type'),\n state: combustionVehicleStateSchema\n .optional()\n .describe('Current state of the combustion vehicle including fuel level'),\n preferences: z.object({}).optional().describe('Combustion vehicle preferences'),\n});\n\nconst electricVehicleParamsSchema = z.object({\n ...baseVehicleParamsSchema,\n engineType: z.literal('electric').describe('Electric engine type'),\n state: electricVehicleStateSchema\n .optional()\n .describe('Current state of the electric vehicle including battery charge'),\n preferences: electricVehiclePreferencesSchema\n .optional()\n .describe('Electric vehicle preferences including charging requirements'),\n});\n\n/**\n * @ignore\n */\nexport const vehicleParametersSchema = z.union([\n z.discriminatedUnion('engineType', [combustionVehicleParamsSchema, electricVehicleParamsSchema]),\n genericVehicleParamsSchema,\n]);\n","/**\n * Known hazardous truck load types. Should be used for trucks carrying hazardous materials.\n */\nexport const loadTypes = [\n 'USHazmatClass1',\n 'USHazmatClass2',\n 'USHazmatClass3',\n 'USHazmatClass4',\n 'USHazmatClass5',\n 'USHazmatClass6',\n 'USHazmatClass7',\n 'USHazmatClass8',\n 'USHazmatClass9',\n 'otherHazmatExplosive',\n 'otherHazmatGeneral',\n 'otherHazmatHarmfulToWater',\n] as const;\n\n/**\n * Known hazardous truck load types. Should be used for trucks carrying hazardous materials.\n *\n * Use these values for routing in the USA:\n * * USHazmatClass1: Explosives\n * * USHazmatClass2: Compressed gas\n * * USHazmatClass3: Flammable liquids\n * * USHazmatClass4: Flammable solids\n * * USHazmatClass5: Oxidizers\n * * USHazmatClass6: Poisons\n * * USHazmatClass7: Radioactive\n * * USHazmatClass8: Corrosives\n * * USHazmatClass9: Miscellaneous\n *\n * Use these values for routing in all other countries:\n * * otherHazmatExplosive: Explosives\n * * otherHazmatGeneral: Miscellaneous\n * * otherHazmatHarmfulToWater: Harmful to water\n */\nexport type LoadType = (typeof loadTypes)[number];\n\n/**\n * Parameters for a vehicle which are related to restrictions (e.g. related to the cargo and purpose of the vehicle).\n */\nexport type VehicleRestrictions = {\n /**\n * Vehicle restrictions including load types, speed limits, ADR codes, and commercial usage.\n */\n restrictions?: {\n /**\n * Specifies types of cargo that may be classified as hazardous materials and are restricted from some roads.\n */\n loadTypes?: LoadType[];\n /**\n * Maximum speed of the vehicle in kilometers/hour.\n * * Must have a value in the range [0, 250].\n * * A value of 0 means that an appropriate value for the vehicle will be determined and applied during route planning.\n *\n * @default 0\n */\n maxSpeedKMH?: number;\n /**\n * Subjects the vehicle to ADR tunnel restrictions.\n * * Vehicles with code B are restricted from roads with ADR tunnel categories B, C, D, and E.\n * * Vehicles with code C are restricted from roads with ADR tunnel categories C, D, and E.\n * * Vehicles with code D are restricted from roads with ADR tunnel categories D and E.\n * * Vehicles with code E are restricted from roads with ADR tunnel category E.\n *\n * Notes:\n * If travelMode is pedestrian or bicycle, adrCode is not considered.\n * The adrCode and loadType parameters are independent; please provide both if applicable.\n * @see https://unece.org/about-adr\n */\n adrCode?: 'B' | 'C' | 'D' | 'E';\n /**\n *\n * The vehicle is used for commercial purposes (big letters on the side) and thus may not be allowed to drive on some roads.\n * This restriction is applicable only in some countries (e.g. US).\n *\n * @default false\n */\n commercial?: boolean;\n };\n};\n","import { avoidableTypes } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { routeTypes } from '../types/commonRoutingParams';\nimport { hasBBoxSchema } from './geometriesSchema';\nimport { vehicleParametersSchema } from './vehicleParamsSchema';\n\n/**\n * @ignore\n */\nexport const commonRoutingRequestSchema = z.object({\n costModel: z\n .object({\n avoid: z\n .array(z.enum(avoidableTypes))\n .optional()\n .describe('Road types and features to avoid when calculating route'),\n traffic: z\n .enum(['live', 'historical'])\n .optional()\n .describe(\n 'Traffic consideration mode (live: real-time + historical, historical: typical patterns only)',\n ),\n routeType: z\n .enum(routeTypes)\n .optional()\n .describe('Route optimization strategy (fast, short, efficient, thrilling)'),\n avoidAreas: z\n .array(hasBBoxSchema)\n .max(10)\n .optional()\n .describe(\n 'Up to 10 rectangular areas for the routing engine to bypass, each as a BBox [W,S,E,N], GeoJSON object, or array of GeoJSON objects',\n ),\n thrillingParams: z\n .object({\n hilliness: z\n .enum(['low', 'normal', 'high'])\n .optional()\n .describe('Level of hilliness for thrilling routes'),\n windingness: z\n .enum(['low', 'normal', 'high'])\n .optional()\n .describe('Level of windingness for thrilling routes'),\n })\n .optional()\n .describe('Optional parameters for thrilling route type'),\n })\n .optional()\n .describe('Cost model criteria for route optimization'),\n travelMode: z.string().optional().describe('Travel mode (car, truck, pedestrian, bicycle)'),\n vehicle: vehicleParametersSchema\n .optional()\n .describe('Vehicle-specific parameters including dimensions, engine type, and consumption model'),\n when: z\n .object({\n option: z.enum(['departAt', 'arriveBy']).describe('Whether to specify a departure or arrival time'),\n date: z.date().describe('The date and time to depart or arrive'),\n })\n .optional()\n .describe('Departure or arrival time specification for route planning'),\n});\n","import type { HasLngLat } from '@tomtom-org/maps-sdk/core';\nimport type { CommonRoutingParams, CommonServiceParams, DepartArriveParams } from '../../shared';\nimport type { ReachableRangeRequestAPI } from './apiRequestTypes';\nimport type { ReachableRangeResponseAPI } from './apiResponseTypes';\n\nexport const budgetTypes = [\n 'timeMinutes',\n 'remainingChargeCPT',\n 'spentChargePCT',\n 'spentFuelLiters',\n 'distanceKM',\n] as const;\n\n/**\n * Type of budget constraint for reachable range calculation.\n *\n * @remarks\n * **Budget Types:**\n * - `timeMinutes`: Travel time in minutes (isochrone)\n * - `distanceKM`: Travel distance in kilometers (isodistance)\n * - `remainingChargeCPT`: Remaining battery charge in percentage (EV)\n * - `spentChargePCT`: Battery charge consumed in percentage (EV)\n * - `spentFuelLiters`: Fuel consumed in liters (combustion)\n *\n * **Common Use Cases:**\n * - Time: \"Where can I reach in 30 minutes?\"\n * - Distance: \"What's within 10 km?\"\n * - EV charge: \"How far can I go on 50% battery?\"\n * - Fuel: \"Range with 20 liters of fuel\"\n *\n * @example\n * ```typescript\n * const timeType: BudgetType = 'timeMinutes';\n * const distanceType: BudgetType = 'distanceKM';\n * const evType: BudgetType = 'remainingChargeCPT';\n * ```\n *\n * @group Reachable Range\n */\nexport type BudgetType = (typeof budgetTypes)[number];\n\n/**\n * Budget constraint for reachable range calculation.\n *\n * Defines the limit (time, distance, or fuel/charge) for calculating\n * how far you can travel from a starting point.\n *\n * @remarks\n * **Use Cases:**\n * - Service area visualization (30-min delivery zone)\n * - EV range anxiety mitigation (show reachable area)\n * - Emergency response coverage (10-min response time)\n * - Delivery zone planning\n * - Store location analysis\n *\n * @example\n * ```typescript\n * // 30-minute travel time\n * const timeBudget: ReachableRangeBudget = {\n * type: 'timeMinutes',\n * value: 30\n * };\n *\n * // 50 km distance\n * const distanceBudget: ReachableRangeBudget = {\n * type: 'distanceKM',\n * value: 50\n * };\n *\n * // 50% battery remaining\n * const evBudget: ReachableRangeBudget = {\n * type: 'remainingChargeCPT',\n * value: 50\n * };\n *\n * // 20 liters of fuel\n * const fuelBudget: ReachableRangeBudget = {\n * type: 'spentFuelLiters',\n * value: 20\n * };\n * ```\n *\n * @group Reachable Range\n */\nexport type ReachableRangeBudget = {\n /**\n * The type of budget, including units.\n *\n * @remarks\n * - `timeMinutes`: Minutes of travel time\n * - `distanceKM`: Kilometers of travel distance\n * - `remainingChargeCPT`: Battery percentage remaining\n * - `spentChargePCT`: Battery percentage consumed\n * - `spentFuelLiters`: Liters of fuel consumed\n */\n type: BudgetType;\n\n /**\n * The value of the budget based on the units mentioned in the type.\n *\n * @remarks\n * **Typical Values:**\n * - Time: 5-60 minutes\n * - Distance: 5-100 km\n * - Charge: 10-100 percentage\n * - Fuel: 5-50 liters\n *\n * @example\n * ```typescript\n * value: 30 // 30 minutes/km/percent/liters depending on type\n * value: 15.5 // Decimal values supported\n * ```\n */\n value: number;\n};\n\n/**\n * Parameters specific to reachable range calculation.\n *\n * @remarks\n * These parameters are combined with common routing parameters to calculate\n * the reachable area from a starting point.\n *\n * @group Reachable Range\n */\nexport type ReachableRangeOwnParams = {\n /**\n * Location from which the range calculation should start.\n *\n * @remarks\n * The center point from which reachability is calculated. Can be:\n * - An object with `lon` and `lat` properties\n * - An array `[longitude, latitude]`\n *\n * @example\n * ```typescript\n * // Object format\n * origin: { lon: 4.9, lat: 52.3 }\n *\n * // Array format\n * origin: [4.9, 52.3]\n * ```\n */\n origin: HasLngLat;\n\n /**\n * The budget for the reachable range calculation.\n *\n * @remarks\n * Consists of a type indicating whether it's about time, distance, or\n * fuel/charge and the units, plus its value.\n *\n * Determines the extent of the reachable area polygon.\n */\n budget: ReachableRangeBudget;\n\n /**\n * Maximum ferry length in meters to consider.\n *\n * @remarks\n * Ferries longer than this value will be avoided in the calculation.\n * Useful for excluding long ferry routes that might extend the range\n * unrealistically.\n *\n * @example\n * ```typescript\n * maxFerryLengthMeters: 5000 // Avoid ferries longer than 5 km\n * ```\n */\n maxFerryLengthMeters?: number;\n\n /**\n * Applies post-processing to smooth the polygon boundary for better visual appearance.\n *\n * @remarks\n * Stronger smoothing generally results in more points.\n *\n * @example\n * ```typescript\n * smoothing: 'strong'\n * ```\n */\n smoothing?: 'none' | 'weak' | 'strong';\n\n /**\n * Specifies when to depart.\n *\n * @remarks\n * If past dates are supplied or dates that are impossible to achieve,\n * it will default to departing now.\n *\n * **Traffic Impact:**\n * - Future departure times use predictive traffic\n * - Current time uses live traffic\n * - Historic times use historical patterns\n *\n * @default Depart now\n *\n * @example\n * ```typescript\n * when: { departAt: new Date('2025-10-20T08:00:00Z') }\n * when: { departAt: 'now' }\n * ```\n */\n when?: DepartArriveParams<'departAt'>;\n};\n\n/**\n * Complete parameters for calculating a reachable range.\n *\n * Combines common service parameters, routing parameters, and reachable range\n * specific options to compute an isochrone or isodistance polygon.\n *\n * @remarks\n * **What it Returns:**\n * A polygon representing the area reachable from the origin within the\n * specified budget (time, distance, or fuel/charge).\n *\n * **Use Cases:**\n * - Delivery zone visualization\n * - Service area mapping\n * - Emergency response coverage\n * - EV range display\n * - Store catchment areas\n * - Real estate search (30-min commute)\n *\n * **Traffic Consideration:**\n * Results vary based on departure time and traffic conditions. Use\n * appropriate `when` values for accurate predictions.\n *\n * @example\n * ```typescript\n * // 30-minute driving range\n * const params: ReachableRangeParams = {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * budget: {\n * type: 'timeMinutes',\n * value: 30\n * },\n * routeType: 'fastest',\n * traffic: 'live',\n * when: { departAt: 'now' }\n * };\n *\n * // 50 km distance range\n * const distanceParams: ReachableRangeParams = {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * budget: {\n * type: 'distanceKM',\n * value: 50\n * }\n * };\n *\n * // EV range with 50% battery\n * const evParams: ReachableRangeParams = {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * budget: {\n * type: 'remainingChargeCPT',\n * value: 50\n * },\n * vehicle: {\n * engineType: 'electric',\n * model: {\n * engine: {\n * consumption: {\n * charging: { maxChargeKWH: 100 }\n * }\n * }\n * },\n * state: {\n * currentChargePCT: 80\n * }\n * }\n * };\n *\n * // Avoid toll roads\n * const noTollParams: ReachableRangeParams = {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * budget: {\n * type: 'timeMinutes',\n * value: 45\n * },\n * avoid: ['tollRoads']\n * };\n * ```\n *\n * @group Reachable Range\n */\nexport type ReachableRangeParams = CommonServiceParams<ReachableRangeRequestAPI, ReachableRangeResponseAPI> &\n CommonRoutingParams &\n ReachableRangeOwnParams;\n","import { z } from 'zod';\nimport { commonRoutingRequestSchema } from '../shared/schema/commonRoutingRequestSchema';\nimport { hasLngLatSchema } from '../shared/schema/geometriesSchema';\nimport { budgetTypes } from './types/reachableRangeParams';\n\n// import { SchemaRefinement } from \"../shared/types/validation\";\n\nconst reachableRangeRequestSchemaMandatory = z.object({\n origin: hasLngLatSchema.describe('Starting position [longitude, latitude] for reachable range calculation'),\n budget: z\n .object({\n type: z.enum(budgetTypes).describe('Budget type (time, distance, or energy/fuel)'),\n value: z.number().min(0).describe('Budget value (depends on type: seconds, meters, liters, or kWh)'),\n })\n .describe('Travel budget constraints for reachable range'),\n});\n\nconst reachableRangeRequestSchemaOptional = z.object({\n maxFerryLengthMeters: z.number().min(0).optional().describe('Maximum ferry distance in meters to include in range'),\n smoothing: z\n .enum(['none', 'weak', 'strong'])\n .optional()\n .describe('Post-processing smoothing level for the polygon boundary'),\n});\n\nconst reachableRangeRequestSchema = commonRoutingRequestSchema.extend(\n reachableRangeRequestSchemaMandatory.extend(reachableRangeRequestSchemaOptional.shape).shape,\n);\n\n// const departArriveRefinement: SchemaRefinement<ReachableRangeParams> = {\n// check: (data: ReachableRangeParams): boolean => (data.when?.option as string) != \"arriveBy\",\n// message: \"When calculating a reachable range, departure date-time can be specified, but not arrival date-time\"\n// };\n\n// const evRangeRefinement: SchemaRefinement<ReachableRangeParams> = {\n// check: (data: ReachableRangeParams): boolean =>\n// !(\n// (data.budget.type === \"remainingChargeCPT\" || data.budget.type === \"spentChargePCT\") &&\n// data.vehicle?.engine?.type != \"electric\"\n// ),\n// message: \"With an EV reachable range, the vehicle parameters must be set, with 'electric' engine type\"\n// };\n//\n// const fuelRangeRefinement: SchemaRefinement<ReachableRangeParams> = {\n// check: (data: ReachableRangeParams): boolean =>\n// !(data.budget.type === \"spentFuelLiters\" && data.vehicle?.engine?.type != \"combustion\"),\n// message: \"With a fuel reachable range, the vehicle parameters must be set, with 'combustion' engine type\"\n// };\n\n/**\n * @ignore\n */\nexport const reachableRangeRequestValidationConfig = {\n schema: reachableRangeRequestSchema,\n // refinements: [evRangeRefinement, fuelRangeRefinement, departArriveRefinement]\n};\n","import { isNil } from 'lodash-es';\nimport {\n CombustionEngineModel,\n ConsumptionModelEfficiency,\n ElectricConsumptionModel,\n ElectricEngineModel,\n SpeedToConsumptionRate,\n VehicleEngineModel,\n VehicleEngineType,\n} from '../types/vehicleEngineParams';\nimport { VehicleDimensions } from '../types/vehicleModel';\nimport { ElectricVehicleParams, VehicleParameters } from '../types/vehicleParams';\nimport { ChargingPreferencesKWH, ChargingPreferencesPCT } from '../types/vehiclePreferences';\nimport { ElectricVehicleStateKWH, ElectricVehicleStatePCT, VehicleState } from '../types/vehicleState';\nimport { appendByRepeatingParamName } from './requestBuildingUtils';\n\nconst appendConsumptionEfficiency = (urlParams: URLSearchParams, efficiency?: ConsumptionModelEfficiency): void => {\n if (efficiency) {\n !isNil(efficiency.acceleration) && urlParams.append('accelerationEfficiency', String(efficiency.acceleration));\n !isNil(efficiency.deceleration) && urlParams.append('decelerationEfficiency', String(efficiency.deceleration));\n !isNil(efficiency.uphill) && urlParams.append('uphillEfficiency', String(efficiency.uphill));\n !isNil(efficiency.downhill) && urlParams.append('downhillEfficiency', String(efficiency.downhill));\n }\n};\n\n// e.g. 50,6.3:130,11.5\nconst buildSpeedToConsumptionString = (speedsToConsumptions: SpeedToConsumptionRate[]): string =>\n speedsToConsumptions\n .map((speedToConsumption) => `${speedToConsumption.speedKMH},${speedToConsumption.consumptionUnitsPer100KM}`)\n .join(':');\n\nconst appendCombustionEngine = (urlParams: URLSearchParams, engine: CombustionEngineModel): void => {\n // (no need to append combustion vehicleEngineType since it's the default)\n const consumptionModel = engine.consumption;\n consumptionModel.speedsToConsumptionsLiters &&\n urlParams.append(\n 'constantSpeedConsumptionInLitersPerHundredkm',\n buildSpeedToConsumptionString(consumptionModel.speedsToConsumptionsLiters),\n );\n !isNil(consumptionModel.auxiliaryPowerInLitersPerHour) &&\n urlParams.append('auxiliaryPowerInLitersPerHour', String(consumptionModel.auxiliaryPowerInLitersPerHour));\n !isNil(consumptionModel.fuelEnergyDensityInMJoulesPerLiter) &&\n urlParams.append(\n 'fuelEnergyDensityInMJoulesPerLiter',\n String(consumptionModel.fuelEnergyDensityInMJoulesPerLiter),\n );\n};\n\nconst appendElectricConsumptionModel = (urlParams: URLSearchParams, model: ElectricConsumptionModel): void => {\n model.speedsToConsumptionsKWH &&\n urlParams.append(\n 'constantSpeedConsumptionInkWhPerHundredkm',\n buildSpeedToConsumptionString(model.speedsToConsumptionsKWH),\n );\n !isNil(model.auxiliaryPowerInkW) && urlParams.append('auxiliaryPowerInkW', String(model.auxiliaryPowerInkW));\n !isNil(model.consumptionInKWHPerKMAltitudeGain) &&\n urlParams.append('consumptionInkWhPerkmAltitudeGain', String(model.consumptionInKWHPerKMAltitudeGain));\n !isNil(model.recuperationInKWHPerKMAltitudeLoss) &&\n urlParams.append('recuperationInkWhPerkmAltitudeLoss', String(model.recuperationInKWHPerKMAltitudeLoss));\n};\n\nconst appendChargingModel = (urlParams: URLSearchParams, engine: ElectricEngineModel): void => {\n const chargingModel = engine.charging;\n if (chargingModel?.maxChargeKWH) {\n urlParams.append('maxChargeInkWh', String(chargingModel.maxChargeKWH));\n }\n // (the rest of the charging model goes as POST data)\n};\n\nconst appendVehicleState = (urlParams: URLSearchParams, vehicleParams: VehicleParameters): void => {\n if (!vehicleParams.state) {\n return;\n }\n\n // Generic state props:\n vehicleParams.state.heading && urlParams.append('vehicleHeading', String(vehicleParams.state.heading));\n\n if (!('engineType' in vehicleParams)) {\n // Generic vehicle, no engine-specific state to append:\n return;\n }\n\n // Engine-specific state props:\n if (vehicleParams.engineType === 'combustion') {\n const combustionState: VehicleState<'combustion'> = vehicleParams.state;\n combustionState.currentFuelInLiters &&\n urlParams.append('currentFuelInLiters', String(combustionState.currentFuelInLiters));\n } else if (vehicleParams.engineType === 'electric') {\n const electricState: VehicleState<'electric'> = vehicleParams.state;\n const kwhElectricState = electricState as ElectricVehicleStateKWH;\n const pctElectricState = electricState as ElectricVehicleStatePCT;\n\n if (kwhElectricState.currentChargeInkWh) {\n urlParams.append('currentChargeInkWh', String(kwhElectricState.currentChargeInkWh));\n } else if (\n pctElectricState.currentChargePCT &&\n vehicleParams.model &&\n 'engine' in vehicleParams.model &&\n vehicleParams.model.engine\n ) {\n const engine = vehicleParams.model.engine;\n const maxChargeKWH = engine.charging?.maxChargeKWH;\n if (maxChargeKWH) {\n // currentChargePCT needs maxChargeKWH to be converted to kWh\n urlParams.append(\n 'currentChargeInkWh',\n String((maxChargeKWH * pctElectricState.currentChargePCT) / 100),\n );\n }\n }\n }\n};\n\nconst appendVehiclePreferences = (urlParams: URLSearchParams, vehicleParams: VehicleParameters): void => {\n if (!vehicleParams.preferences) {\n return;\n }\n\n if ('engineType' in vehicleParams && vehicleParams.engineType === 'electric') {\n const preferences = vehicleParams.preferences;\n if (preferences.chargingPreferences) {\n const chargingPrefs = preferences.chargingPreferences;\n const kwhChargingPrefs = chargingPrefs as ChargingPreferencesKWH;\n const pctChargingPrefs = chargingPrefs as ChargingPreferencesPCT;\n\n // Check if absolute kWh values are available and use them directly\n if (kwhChargingPrefs.minChargeAtChargingStopsInkWh || kwhChargingPrefs.minChargeAtDestinationInkWh) {\n urlParams.append('minChargeAtDestinationInkWh', String(kwhChargingPrefs.minChargeAtDestinationInkWh));\n urlParams.append(\n 'minChargeAtChargingStopsInkWh',\n String(kwhChargingPrefs.minChargeAtChargingStopsInkWh),\n );\n } else if (\n (pctChargingPrefs.minChargeAtChargingStopsPCT || pctChargingPrefs.minChargeAtDestinationPCT) &&\n vehicleParams.model &&\n 'engine' in vehicleParams.model &&\n vehicleParams.model.engine\n ) {\n // Considering percentage values if absolute values not available and maxChargeKWH exists\n const engine = vehicleParams.model.engine;\n const maxChargeKWH = engine.charging?.maxChargeKWH;\n if (maxChargeKWH) {\n urlParams.append(\n 'minChargeAtDestinationInkWh',\n String((maxChargeKWH * pctChargingPrefs.minChargeAtDestinationPCT) / 100),\n );\n urlParams.append(\n 'minChargeAtChargingStopsInkWh',\n String((maxChargeKWH * pctChargingPrefs.minChargeAtChargingStopsPCT) / 100),\n );\n }\n }\n }\n }\n};\n\nconst appendVehicleDimensions = (urlParams: URLSearchParams, dimensions?: VehicleDimensions): void => {\n if (dimensions) {\n // (defaults are 0):\n dimensions.lengthMeters && urlParams.append('vehicleLength', String(dimensions.lengthMeters));\n dimensions.heightMeters && urlParams.append('vehicleHeight', String(dimensions.heightMeters));\n dimensions.widthMeters && urlParams.append('vehicleWidth', String(dimensions.widthMeters));\n dimensions.weightKG && urlParams.append('vehicleWeight', String(dimensions.weightKG));\n dimensions.axleWeightKG && urlParams.append('vehicleAxleWeight', String(dimensions.axleWeightKG));\n }\n};\n\nconst appendVehicleRestrictions = (urlParams: URLSearchParams, vehicleParams: VehicleParameters): void => {\n // Vehicle restrictions from VehicleRestrictions intersection:\n const restrictions = vehicleParams.restrictions;\n if (!restrictions) {\n return;\n }\n\n appendByRepeatingParamName(urlParams, 'vehicleLoadType', restrictions.loadTypes);\n restrictions.adrCode && urlParams.append('vehicleAdrTunnelRestrictionCode', restrictions.adrCode);\n restrictions.commercial && urlParams.append('vehicleCommercial', String(restrictions.commercial));\n // (default is 0):\n restrictions.maxSpeedKMH && urlParams.append('vehicleMaxSpeed', String(restrictions.maxSpeedKMH));\n};\n\nconst appendVehicleEngineModel = (\n urlParams: URLSearchParams,\n engineType: VehicleEngineType,\n engine: VehicleEngineModel<VehicleEngineType>,\n): void => {\n // (efficiency params have the same names between engine types)\n appendConsumptionEfficiency(urlParams, engine.consumption.efficiency);\n\n if (engineType === 'electric') {\n appendElectricConsumptionModel(urlParams, (engine as ElectricEngineModel).consumption);\n appendChargingModel(urlParams, engine as ElectricEngineModel);\n } else {\n // (no need to append combustion vehicleEngineType since it's the default)\n appendCombustionEngine(urlParams, engine as CombustionEngineModel);\n }\n};\n\nconst appendVehicleModel = (urlParams: URLSearchParams, vehicleParams: VehicleParameters): void => {\n if (!vehicleParams.model) {\n return;\n }\n\n // Handle predefined vehicle model\n if ('variantId' in vehicleParams.model) {\n urlParams.append('vehicleModelId', vehicleParams.model.variantId);\n } else {\n // Handle explicit vehicle model (dimensions and engine)\n appendVehicleDimensions(urlParams, vehicleParams.model.dimensions);\n\n if (vehicleParams.model.engine) {\n appendVehicleEngineModel(\n urlParams,\n 'engineType' in vehicleParams ? vehicleParams.engineType : undefined,\n vehicleParams.model.engine,\n );\n }\n }\n};\n\n/**\n * Appends vehicle parameters to the URL search params for routing requests.\n * @param urlParams - The URLSearchParams to append to\n * @param vehicleParams - The vehicle parameters to append\n */\nexport const appendVehicleParams = (urlParams: URLSearchParams, vehicleParams?: VehicleParameters): void => {\n if (!vehicleParams) {\n return;\n }\n\n // the engine type defaults to combustion, thus we only bother to append it if it's electric:\n if ((vehicleParams as ElectricVehicleParams).engineType === 'electric') {\n urlParams.append('vehicleEngineType', 'electric');\n }\n\n appendVehicleModel(urlParams, vehicleParams);\n appendVehicleState(urlParams, vehicleParams);\n appendVehiclePreferences(urlParams, vehicleParams);\n appendVehicleRestrictions(urlParams, vehicleParams);\n};\n","import type { CommonRoutingParams, DepartArriveParams } from '../types/commonRoutingParams';\nimport { appendByRepeatingParamName, appendOptionalParam } from './requestBuildingUtils';\nimport { appendVehicleParams } from './routingVehicleParamsBuilder';\n\nconst appendWhenParams = (urlParams: URLSearchParams, when?: DepartArriveParams): void => {\n if (when?.date) {\n const formattedDate = when.date.toISOString();\n if (when.option === 'departAt') {\n urlParams.append('departAt', formattedDate);\n } else if (when.option === 'arriveBy') {\n urlParams.append('arriveAt', formattedDate);\n }\n }\n};\n\n// TODO: not supported yet in Orbis\n// const appendThrillingParams = (urlParams: URLSearchParams, thrillingParams?: ThrillingParams): void => {\n// if (thrillingParams) {\n// thrillingParams.hilliness && urlParams.append('hilliness', thrillingParams.hilliness);\n// thrillingParams.windingness && urlParams.append('windingness', thrillingParams.windingness);\n// }\n// };\n\n/**\n * @ignore\n */\nexport const appendCommonRoutingParams = (urlParams: URLSearchParams, params: CommonRoutingParams): void => {\n const costModel = params.costModel;\n appendByRepeatingParamName(urlParams, 'avoid', costModel?.avoid);\n appendOptionalParam(urlParams, 'traffic', costModel?.traffic);\n appendWhenParams(urlParams, params.when);\n appendOptionalParam(urlParams, 'routeType', costModel?.routeType);\n // TODO not supported in Orbis\n // if (costModel?.routeType === 'thrilling') {\n // appendThrillingParams(urlParams, costModel.thrillingParams);\n // }\n appendOptionalParam(urlParams, 'travelMode', params.travelMode);\n appendVehicleParams(urlParams, params.vehicle);\n};\n","import { getPositionStrict } from '@tomtom-org/maps-sdk/core';\nimport type { Position } from 'geojson';\nimport type { FetchInput } from '../shared';\nimport { appendCommonRoutingParams } from '../shared/request/commonRoutingRequestBuilder';\nimport { appendCommonParams, appendOptionalParam } from '../shared/request/requestBuildingUtils';\nimport type { ElectricVehicleParams } from '../shared/types/vehicleParams';\nimport type { ElectricVehicleStatePCT } from '../shared/types/vehicleState';\nimport type { ReachableRangePostData } from './types/apiRequestTypes';\nimport type { ReachableRangeParams } from './types/reachableRangeParams';\n\nconst buildUrlBasePath = (params: ReachableRangeParams): string =>\n params.customServiceBaseURL ?? `${params.commonBaseURL}/maps/orbis/routing/calculateReachableRange`;\n\nconst getMaxChargeKWH = (params: ReachableRangeParams): number | undefined => {\n const vehicle = params.vehicle as ElectricVehicleParams | undefined;\n if (!vehicle?.model || !('engine' in vehicle.model)) {\n return undefined;\n }\n return vehicle.model.engine?.charging?.maxChargeKWH;\n};\n\nconst getCurrentChargeKWH = (params: ReachableRangeParams): number | undefined => {\n const vehicle = params.vehicle as ElectricVehicleParams | undefined;\n if (!vehicle?.state) {\n return undefined;\n }\n const pctState = vehicle.state as ElectricVehicleStatePCT;\n if (pctState.currentChargePCT != null) {\n const maxChargeKWH = getMaxChargeKWH(params);\n if (maxChargeKWH != null) {\n return (maxChargeKWH * pctState.currentChargePCT) / 100;\n }\n }\n return undefined;\n};\n\nconst appendBudget = (urlParams: URLSearchParams, params: ReachableRangeParams): void => {\n const budget = params.budget;\n switch (budget.type) {\n case 'timeMinutes':\n urlParams.append('timeBudgetInSec', (budget.value * 60).toString());\n break;\n case 'distanceKM':\n urlParams.append('distanceBudgetInMeters', (budget.value * 1000).toString());\n break;\n case 'spentFuelLiters':\n urlParams.append('fuelBudgetInLiters', budget.value.toString());\n break;\n case 'spentChargePCT': {\n const maxChargeKWH = getMaxChargeKWH(params);\n if (maxChargeKWH != null) {\n urlParams.append('energyBudgetInkWh', ((maxChargeKWH * budget.value) / 100).toString());\n }\n break;\n }\n case 'remainingChargeCPT': {\n const currentChargeKWH = getCurrentChargeKWH(params);\n const maxChargeKWH = getMaxChargeKWH(params);\n if (maxChargeKWH != null && currentChargeKWH != null) {\n const remainingKWH = (maxChargeKWH * budget.value) / 100;\n urlParams.append('energyBudgetInkWh', Math.max(0, currentChargeKWH - remainingKWH).toString());\n }\n break;\n }\n default:\n // Unsupported by SDK but will attempt to send it anyway\n urlParams.append(budget.type, budget.value.toString());\n }\n};\n\nconst buildPostData = (params: ReachableRangeParams): ReachableRangePostData => {\n const position: Position = getPositionStrict(params.origin);\n return {\n origin: { type: 'Point', coordinates: [position[0], position[1]] },\n };\n};\n\n/**\n * @param params\n * @returns\n */\nexport const buildReachableRangeRequest = (params: ReachableRangeParams): FetchInput<ReachableRangePostData> => {\n const url = new URL(buildUrlBasePath(params));\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n // Currently reachable range API does not support language: https://developer.tomtom.com/routing-api/documentation/tomtom-orbis-maps/v3/calculate-reachable-range\n urlParams.delete('language');\n appendCommonRoutingParams(urlParams, params);\n appendBudget(urlParams, params);\n appendOptionalParam(urlParams, 'maxFerryLengthInMeters', params.maxFerryLengthMeters);\n appendOptionalParam(urlParams, 'smoothing', params.smoothing);\n return { method: 'POST', url, data: buildPostData(params) };\n};\n","import type { BBox, PolygonFeature } from '@tomtom-org/maps-sdk/core';\nimport { bboxFromGeoJSON } from '@tomtom-org/maps-sdk/core';\nimport type { Polygon } from 'geojson';\nimport type { ReachableRangeResponseAPI } from './types/apiResponseTypes';\nimport type { ReachableRangeParams } from './types/reachableRangeParams';\n\n/**\n *\n * @param apiResponse\n * @param params\n */\nexport const parseReachableRangeResponse = (\n apiResponse: ReachableRangeResponseAPI,\n params: ReachableRangeParams,\n): PolygonFeature<ReachableRangeParams> => {\n const geometry: Polygon = {\n type: 'Polygon',\n coordinates: [apiResponse.reachableRange.boundary.map((point) => [point.longitude, point.latitude])],\n };\n const bbox = bboxFromGeoJSON(geometry) as BBox; // the geometry should always have a bbox\n return { type: 'Feature', geometry, bbox, properties: params };\n};\n","import type { PolygonFeature } from '@tomtom-org/maps-sdk/core';\nimport { parseRoutingResponseError } from '../routing/routingResponseErrorParser';\nimport type { ServiceTemplate } from '../shared';\nimport { fetchWith } from '../shared/fetch';\nimport { reachableRangeRequestValidationConfig } from './reachableRangeRequestSchema';\nimport { buildReachableRangeRequest } from './requestBuilder';\nimport { parseReachableRangeResponse } from './responseParser';\nimport type { ReachableRangeRequestAPI } from './types/apiRequestTypes';\nimport type { ReachableRangeResponseAPI } from './types/apiResponseTypes';\nimport type { ReachableRangeParams } from './types/reachableRangeParams';\n\nexport type ReachableRangeTemplate = ServiceTemplate<\n ReachableRangeParams,\n ReachableRangeRequestAPI,\n ReachableRangeResponseAPI,\n PolygonFeature<ReachableRangeParams>\n>;\n\nexport const reachableRangeTemplate: ReachableRangeTemplate = {\n requestValidation: reachableRangeRequestValidationConfig,\n buildRequest: buildReachableRangeRequest,\n sendRequest: fetchWith,\n parseResponse: parseReachableRangeResponse,\n parseResponseError: parseRoutingResponseError,\n getAPIVersion: () => 3,\n};\n","import type { ReachableRangeTemplate } from './reachableRangeTemplate';\nimport { reachableRangeTemplate } from './reachableRangeTemplate';\nimport { buildReachableRangeRequest } from './requestBuilder';\nimport { parseReachableRangeResponse } from './responseParser';\n\nconst customize: {\n buildReachableRangeRequest: typeof buildReachableRangeRequest;\n parseReachableRangeResponse: typeof parseReachableRangeResponse;\n reachableRangeTemplate: ReachableRangeTemplate;\n} = {\n buildReachableRangeRequest,\n parseReachableRangeResponse,\n reachableRangeTemplate,\n};\nexport default customize;\n","import { getPositionStrict } from '@tomtom-org/maps-sdk/core';\nimport { isNil } from 'lodash-es';\nimport type { CommonServiceParams } from '../shared';\nimport { arrayToCSV } from '../shared/arrays';\nimport { PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport { appendCommonParams } from '../shared/request/requestBuildingUtils';\nimport type { ReverseGeocodingParams } from './types/reverseGeocodingParams';\n\nconst buildUrlBasePath = (params: CommonServiceParams): string =>\n params.customServiceBaseURL || `${params.commonBaseURL}${PLACES_URL_PATH}/reverseGeocode`;\n\n/**\n * Default function for building a reverse geocoding request from {@link ReverseGeocodingParams}\n * @param params The reverse geocoding parameters, with global configuration already merged into them.\n */\nexport const buildRevGeoRequest = (params: ReverseGeocodingParams): URL => {\n const lngLat = getPositionStrict(params.position);\n const url = new URL(`${buildUrlBasePath(params)}/${lngLat[1]},${lngLat[0]}.json`);\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n\n // rev-geo specific parameters:\n params.allowFreeformNewline && urlParams.append('allowFreeformNewline', String(params.allowFreeformNewline));\n params.geographyType && urlParams.append('entityType', arrayToCSV(params.geographyType));\n !isNil(params.heading) && urlParams.append('heading', String(params.heading));\n params.mapcodes && urlParams.append('mapcodes', arrayToCSV(params.mapcodes));\n params.number && urlParams.append('number', params.number);\n !isNil(params.radiusMeters) && urlParams.append('radius', String(params.radiusMeters));\n params.returnSpeedLimit && urlParams.append('returnSpeedLimit', String(params.returnSpeedLimit));\n params.returnRoadUse && urlParams.append('returnRoadUse', String(params.returnRoadUse));\n params.roadUses && urlParams.append('roadUse', JSON.stringify(params.roadUses));\n return url;\n};\n","import { generateId, getPositionStrict, toPointGeometry } from '@tomtom-org/maps-sdk/core';\nimport { apiToGeoJSONBBox, csvLatLngToPosition } from '../shared/geometry';\nimport type { ReverseGeocodingResponse } from './reverseGeocoding';\nimport type { ReverseGeocodingResponseAPI } from './types/apiTypes';\nimport type { ReverseGeocodingParams } from './types/reverseGeocodingParams';\n\n/**\n * Default method for parsing reverse geocoding request from {@link ReverseGeocodingResponse}\n * @param params\n * @param apiResponse\n */\nexport const parseRevGeoResponse = (\n apiResponse: ReverseGeocodingResponseAPI,\n params: ReverseGeocodingParams,\n): ReverseGeocodingResponse => {\n const firstApiResult = apiResponse.addresses[0];\n const { boundingBox, sideOfStreet, offsetPosition, ...address } = firstApiResult?.address || {};\n return {\n type: 'Feature',\n // The requested coordinates are the primary ones, and set as the GeoJSON Feature geometry:\n geometry: toPointGeometry(getPositionStrict(params.position)),\n ...(boundingBox && { bbox: apiToGeoJSONBBox(boundingBox) }),\n id: generateId(),\n ...(firstApiResult && {\n properties: {\n type: firstApiResult?.entityType ? 'Geography' : !address.streetNumber ? 'Street' : 'Point Address',\n address,\n ...(firstApiResult.dataSources && { dataSources: firstApiResult.dataSources }),\n ...(firstApiResult.mapcodes && { mapcodes: firstApiResult.mapcodes }),\n ...(sideOfStreet && { sideOfStreet }),\n ...(offsetPosition && { offsetPosition: csvLatLngToPosition(offsetPosition) }),\n // The reverse geocoded coordinates are secondary and set in the GeoJSON properties:\n originalPosition: csvLatLngToPosition(firstApiResult.position),\n },\n }),\n };\n};\n","import { views } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { hasLngLatSchema } from '../shared/schema/geometriesSchema';\n\nconst revGeocodeRequestMandatory = z.object({\n position: hasLngLatSchema.describe('Geographic position [longitude, latitude] to reverse geocode'),\n});\n\nconst revGeocodeRequestOptional = z.object({\n allowFreeformNewline: z.boolean().optional().describe('Allow newline characters in freeform address'),\n geographyType: z.array(z.string()).optional().describe('Filter results to specific geography types'),\n heading: z\n .number()\n .min(-360)\n .max(360)\n .optional()\n .describe('Vehicle heading in degrees (-360 to 360) for directional results'),\n mapcodes: z.array(z.string()).optional().describe('Request mapcode representations for location'),\n number: z.string().optional().describe('Street number for more precise address results'),\n radiusMeters: z.number().optional().describe('Search radius in meters for reverse geocoding'),\n returnMatchType: z.boolean().optional().describe('Include match type information in response'),\n returnRoadUse: z.boolean().optional().describe('Include road use information in response'),\n returnSpeedLimit: z.boolean().optional().describe('Include speed limit information in response'),\n roadUses: z.array(z.string()).optional().describe('Filter results to specific road use types'),\n view: z.enum(views).optional().describe('Geopolitical view for disputed territories'),\n});\n\n/**\n * @ignore\n */\nexport const revGeocodeRequestSchema = revGeocodeRequestMandatory.extend(revGeocodeRequestOptional.shape);\n","import type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { buildRevGeoRequest } from './requestBuilder';\nimport { parseRevGeoResponse } from './responseParser';\nimport type { ReverseGeocodingResponse } from './reverseGeocoding';\nimport { revGeocodeRequestSchema } from './revGeocodeRequestSchema';\nimport type { ReverseGeocodingResponseAPI } from './types/apiTypes';\nimport type { ReverseGeocodingParams } from './types/reverseGeocodingParams';\n\n/**\n * Reverse Geocoding service template type.\n * @ignore\n */\nexport type ReverseGeocodingTemplate = ServiceTemplate<\n ReverseGeocodingParams,\n URL,\n ReverseGeocodingResponseAPI,\n ReverseGeocodingResponse\n>;\n\n/**\n * Reverse Geocoding service template main implementation.\n * @ignore\n */\nexport const reverseGeocodingTemplate: ReverseGeocodingTemplate = {\n requestValidation: { schema: revGeocodeRequestSchema },\n buildRequest: buildRevGeoRequest,\n sendRequest: get,\n parseResponse: parseRevGeoResponse,\n};\n","import { buildRevGeoRequest } from './requestBuilder';\nimport { parseRevGeoResponse } from './responseParser';\nimport type { ReverseGeocodingTemplate } from './reverseGeocodingTemplate';\nimport { reverseGeocodingTemplate } from './reverseGeocodingTemplate';\n\nconst customize: {\n buildRevGeoRequest: typeof buildRevGeoRequest;\n parseRevGeoResponse: typeof parseRevGeoResponse;\n reverseGeocodingTemplate: ReverseGeocodingTemplate;\n} = {\n buildRevGeoRequest,\n parseRevGeoResponse,\n reverseGeocodingTemplate,\n};\nexport default customize;\n","import type { SectionType } from '@tomtom-org/maps-sdk/core';\nimport { getRoutePlanningLocationType, inputSectionTypesWithGuidance } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { commonRoutingRequestSchema } from '../shared/schema/commonRoutingRequestSchema';\nimport {\n featureSchema,\n geometrySchema,\n hasLngLatSchema,\n lineStringCoordsSchema,\n} from '../shared/schema/geometriesSchema';\nimport type { SchemaRefinement } from '../shared/types/validation';\nimport type { CalculateRouteParams } from './types/calculateRouteParams';\n\nconst waypointLikeSchema = z.union([hasLngLatSchema, geometrySchema]).describe('Waypoint as position or geometry');\nconst pathLikeSchema = z\n .union([lineStringCoordsSchema, featureSchema])\n .describe('Path as line string coordinates or feature');\n\nconst mandatorySchema = z.object({\n locations: z\n .array(z.union([waypointLikeSchema, pathLikeSchema]))\n .min(1)\n .describe('Array of route locations (waypoints or paths) - minimum 2 waypoints or 1 path required'), // see calculateRouteLocationsRefinement\n});\n\nconst optionalSchema = z.object({\n computeAdditionalTravelTimeFor: z\n .enum(['none', 'all'])\n .optional()\n .describe('Calculate additional travel time estimates for different traffic scenarios (none or all)'),\n vehicleHeading: z\n .number()\n .min(0)\n .max(359.5)\n .optional()\n .describe('Vehicle heading in degrees (0-359.5) at departure'),\n // TODO add proper instructionsInfo check\n // instructionsType: z.enum(instructionsTypes),\n maxAlternatives: z\n .number()\n .min(0)\n .max(5)\n .optional()\n .describe('Maximum number of alternative routes to calculate (0-5)'),\n sectionTypes: z\n .array(z.enum(inputSectionTypesWithGuidance as [SectionType, ...SectionType[]]))\n .optional()\n .describe('Types of route sections to include in response (toll, ferry, traffic, etc.)'),\n});\n\nconst schema = commonRoutingRequestSchema.extend(mandatorySchema.extend(optionalSchema.shape).shape);\n\nconst locationsRefinement: SchemaRefinement<CalculateRouteParams> = {\n check: (data: CalculateRouteParams): boolean => {\n const routePlanningLocationTypes = data.locations.map(getRoutePlanningLocationType);\n if (!routePlanningLocationTypes.includes('path')) {\n return data.locations.length >= 2;\n }\n return true; // see calculateRouteRequestSchemaMandatory\n },\n message:\n 'When passing waypoints only: at least 2 must be defined. ' +\n 'If passing also paths, at least one path must be defined',\n};\n\n/**\n * @ignore\n */\nexport const routeRequestValidationConfig = { schema, refinements: [locationsRefinement] };\n","import type {\n GetPositionEntryPointOption,\n HasBBox,\n PathLike,\n RoutePlanningLocation,\n RoutePlanningLocationType,\n Waypoint,\n WaypointLike,\n WaypointProps,\n} from '@tomtom-org/maps-sdk/core';\nimport {\n bboxFromGeoJSON,\n getPositionStrict,\n getRoutePlanningLocationType,\n inputSectionTypes,\n inputSectionTypesWithGuidance,\n} from '@tomtom-org/maps-sdk/core';\nimport type { Position } from 'geojson';\nimport { isNil, omit } from 'lodash-es';\nimport type { FetchInput } from '../shared';\nimport { VehiclePreferences } from '../shared';\nimport { positionToCSVLatLon } from '../shared/geometry';\nimport { appendCommonRoutingParams } from '../shared/request/commonRoutingRequestBuilder';\nimport {\n appendByRepeatingParamName,\n appendCommonParams,\n appendOptionalParam,\n} from '../shared/request/requestBuildingUtils';\nimport { ExplicitVehicleModel } from '../shared/types/vehicleModel';\nimport type { AvoidAreasAPI, CalculateRoutePOSTDataAPI, PointWaypointAPI } from './types/apiRequestTypes';\nimport type { LatitudeLongitudePointAPI } from './types/apiResponseTypes';\nimport type { CalculateRouteParams, GuidanceParams, InputSectionTypes } from './types/calculateRouteParams';\n\n// Are these params about Long Distance EV Routing:\nconst getChargingPreferences = (params: CalculateRouteParams) =>\n (params.vehicle?.preferences as VehiclePreferences<'electric'>)?.chargingPreferences;\n\nconst buildUrlBasePath = (params: CalculateRouteParams): string =>\n params.customServiceBaseURL ||\n `${params.commonBaseURL}/maps/orbis/routing/${getChargingPreferences(params) ? 'calculateLongDistanceEVRoute' : 'calculateRoute'}`;\n\nconst getWaypointProps = (waypointInput: WaypointLike): WaypointProps | null =>\n (waypointInput as Waypoint).properties || null;\n\nconst defaultUseEntryPointOption: GetPositionEntryPointOption = 'main-when-available';\n\nconst buildLocationsStringFromWaypoints = (\n waypointInputs: WaypointLike[],\n useEntryPoint: GetPositionEntryPointOption,\n): string =>\n waypointInputs\n .map((waypointInput: WaypointLike) => {\n const lngLatString = positionToCSVLatLon(getPositionStrict(waypointInput, { useEntryPoint }));\n const radius = getWaypointProps(waypointInput)?.radiusMeters;\n return radius ? `circle(${lngLatString},${radius})` : lngLatString;\n })\n .join(':');\n\nconst getPositionsFromPath = (pathLike: PathLike): Position[] => {\n if (Array.isArray(pathLike)) {\n return pathLike;\n }\n return pathLike.geometry.coordinates;\n};\n\nconst getFirstAndLastPoints = (\n locations: RoutePlanningLocation[],\n types: RoutePlanningLocationType[],\n useEntryPoint: GetPositionEntryPointOption,\n): [Position, Position] => {\n let firstPoint;\n const firstRoutePlanningLocation = locations[0];\n if (types[0] === 'path') {\n const positions = getPositionsFromPath(firstRoutePlanningLocation as PathLike);\n firstPoint = positions[0];\n } else {\n firstPoint = getPositionStrict(firstRoutePlanningLocation as WaypointLike, { useEntryPoint });\n }\n\n const lastRoutePlanningLocation = locations[locations.length - 1];\n let lastPoint;\n if (types[types.length - 1] === 'path') {\n const positions = getPositionsFromPath(lastRoutePlanningLocation as PathLike);\n lastPoint = positions[positions.length - 1];\n } else {\n lastPoint = getPositionStrict(lastRoutePlanningLocation as WaypointLike, { useEntryPoint });\n }\n\n return [firstPoint, lastPoint];\n};\n\nconst buildLocationsString = (\n locations: RoutePlanningLocation[],\n routePlanningLocationTypes: RoutePlanningLocationType[],\n useEntryPoint: GetPositionEntryPointOption,\n): string =>\n buildLocationsStringFromWaypoints(\n routePlanningLocationTypes.includes('path')\n ? getFirstAndLastPoints(locations, routePlanningLocationTypes, useEntryPoint)\n : (locations as WaypointLike[]),\n useEntryPoint,\n );\n\nconst appendSectionTypes = (\n urlParams: URLSearchParams,\n sectionTypes: InputSectionTypes | undefined,\n instructionsInclude: boolean,\n): void => {\n const effectiveSectionTypes = (\n sectionTypes ?? (instructionsInclude ? inputSectionTypesWithGuidance : inputSectionTypes)\n ).map((sectionType) => (sectionType === 'vehicleRestricted' ? 'travelMode' : sectionType));\n appendByRepeatingParamName(urlParams, 'sectionType', effectiveSectionTypes);\n};\n\nconst appendGuidanceParams = (urlParams: URLSearchParams, params?: CalculateRouteParams): void => {\n if (params?.guidance) {\n const guidance: GuidanceParams = params.guidance;\n urlParams.append('instructionsType', guidance.type);\n urlParams.append('guidanceVersion', String(guidance.version ?? 2));\n urlParams.append('instructionPhonetics', guidance.phonetics ?? 'IPA');\n urlParams.append('language', params.language ?? 'en-US');\n }\n};\n\nconst toLatLngPointApi = (position: Position): LatitudeLongitudePointAPI => ({\n latitude: position[1],\n longitude: position[0],\n});\n\n// appends a path into the given post data, adding to supportingPoints and pointWaypoints as applicable\nconst appendPathPostData = (\n pathRoutePlanningLocation: PathLike,\n routePlanningLocationIndex: number,\n locations: RoutePlanningLocation[],\n supportingPoints: LatitudeLongitudePointAPI[],\n pointWaypoints: PointWaypointAPI[],\n): void => {\n // first, we add the supportingPoints from the path coordinates:\n const supportingPointsLengthBeforePath = supportingPoints.length;\n for (const position of getPositionsFromPath(pathRoutePlanningLocation)) {\n supportingPoints.push(toLatLngPointApi(position));\n }\n // then we check if it's a route, and if so we add waypoints from its legs as applicable\n // (a route leg is the portion of the path between 2 waypoints)\n if (!Array.isArray(pathRoutePlanningLocation)) {\n const legs = pathRoutePlanningLocation.properties.sections.leg;\n // (We assume all routes have at least 1 leg)\n legs.forEach((leg, legIndex) => {\n // If the route is the first geo-input, we skip adding the leg...\n // ... since it's expected to be already in the origin \"location\"\n if (routePlanningLocationIndex > 0 || legIndex > 0) {\n pointWaypoints.push({\n supportingPointIndex: supportingPointsLengthBeforePath + (leg.startPointIndex as number),\n waypointSourceType: 'USER_DEFINED',\n });\n }\n });\n // If the route isn't the last geo-input, we add its destination as pointWaypoint too:\n // (If it's the last geo-input, we skip adding the leg...\n // ... since it's expected to be already in the destination \"location\")\n if (routePlanningLocationIndex < locations.length - 1) {\n pointWaypoints.push({\n supportingPointIndex:\n supportingPointsLengthBeforePath + pathRoutePlanningLocation.geometry.coordinates.length - 1,\n waypointSourceType: 'USER_DEFINED',\n });\n }\n }\n};\n\n// appends a waypoint into the given post data, adding to supportingPoints and pointWaypoints as applicable\nconst appendWaypointPostData = (\n waypoint: WaypointLike,\n routePlanningLocationIndex: number,\n locations: RoutePlanningLocation[],\n supportingPoints: LatitudeLongitudePointAPI[],\n pointWaypoints: PointWaypointAPI[],\n useEntryPoint: GetPositionEntryPointOption,\n) => {\n // individual points are treated like POST waypoints\n supportingPoints.push(toLatLngPointApi(getPositionStrict(waypoint, { useEntryPoint })));\n // for origin and destination we do not add pointWaypoints, since they end up as the URL \"locations\":\n if (routePlanningLocationIndex > 0 && routePlanningLocationIndex < locations.length - 1) {\n pointWaypoints.push({\n supportingPointIndex: supportingPoints.length - 1,\n waypointSourceType: 'USER_DEFINED',\n });\n }\n};\n\nconst buildlocationsPostData = (\n locations: RoutePlanningLocation[],\n types: RoutePlanningLocationType[],\n useEntryPoints: GetPositionEntryPointOption,\n): { supportingPoints: LatitudeLongitudePointAPI[]; pointWaypoints?: PointWaypointAPI[] } => {\n const supportingPoints: LatitudeLongitudePointAPI[] = [];\n const pointWaypoints: PointWaypointAPI[] = [];\n\n locations.forEach((routePlanningLocation, routePlanningLocationIndex) => {\n if (types[routePlanningLocationIndex] === 'path') {\n appendPathPostData(\n routePlanningLocation as PathLike,\n routePlanningLocationIndex,\n locations,\n supportingPoints,\n pointWaypoints,\n );\n } else {\n appendWaypointPostData(\n routePlanningLocation as WaypointLike,\n routePlanningLocationIndex,\n locations,\n supportingPoints,\n pointWaypoints,\n useEntryPoints,\n );\n }\n });\n\n return { supportingPoints, ...(pointWaypoints.length && { pointWaypoints }) };\n};\n\nconst buildAvoidAreasPostData = (avoidAreas: HasBBox[]): AvoidAreasAPI => ({\n rectangles: avoidAreas.map((rect: HasBBox) => {\n const bbox = bboxFromGeoJSON(rect);\n if (!bbox) {\n throw new Error('Could not derive a bounding box from an avoidAreas rectangle');\n }\n const [west, south, east, north] = bbox;\n return {\n southWestCorner: { latitude: south, longitude: west },\n northEastCorner: { latitude: north, longitude: east },\n };\n }),\n});\n\nconst buildPostData = (\n params: CalculateRouteParams,\n types: RoutePlanningLocationType[],\n useEntryPoints: GetPositionEntryPointOption,\n): CalculateRoutePOSTDataAPI | null => {\n const pathsIncluded = types.includes('path');\n const isLdevr = !!getChargingPreferences(params);\n const avoidAreas = params.costModel?.avoidAreas;\n if (!pathsIncluded && !isLdevr && !avoidAreas) {\n // (if no paths in the given locations nor LDEVR nor avoidAreas, there'll be no POST data, which will trigger a GET call)\n return null;\n }\n\n const vehicleModel = params.vehicle?.model as ExplicitVehicleModel<'electric'>;\n const chargingModel = vehicleModel?.engine?.charging;\n return {\n ...(pathsIncluded && buildlocationsPostData(params.locations, types, useEntryPoints)),\n ...(isLdevr &&\n chargingModel && {\n chargingParameters: omit(chargingModel, 'maxChargeKWH'),\n }),\n ...(avoidAreas?.length && { avoidAreas: buildAvoidAreasPostData(avoidAreas) }),\n };\n};\n\n/**\n * Default function for building calculate route request from {@link CalculateRouteParams}\n * @param params The calculate route parameters, with global configuration already merged into them.\n */\nexport const buildCalculateRouteRequest = (params: CalculateRouteParams): FetchInput<CalculateRoutePOSTDataAPI> => {\n const routePlanningLocationTypes = params.locations.map(getRoutePlanningLocationType);\n const useEntryPoints = params.useEntryPoints ?? defaultUseEntryPointOption;\n const url = new URL(\n `${buildUrlBasePath(params)}/${buildLocationsString(params.locations, routePlanningLocationTypes, useEntryPoints)}/json`,\n );\n const urlParams: URLSearchParams = url.searchParams;\n appendCommonParams(urlParams, params);\n if (!('language' in params)) {\n // for routing we ensure to always have a default language input since by default we fetch some language-specific sections:\n // (see importantRoadStretch as default, and instructionsType when guidance is provided)\n // It's still possible to force the language to be undefined if skipping such sections for performance reasons\n urlParams.append('language', 'en-GB');\n }\n appendCommonRoutingParams(urlParams, params);\n appendOptionalParam(urlParams, 'computeTravelTimeFor', params.computeAdditionalTravelTimeFor);\n appendGuidanceParams(urlParams, params);\n !isNil(params.maxAlternatives) && urlParams.append('maxAlternatives', String(params.maxAlternatives));\n appendSectionTypes(urlParams, params.sectionTypes, !!params.guidance?.type);\n for (const representation of params.extendedRouteRepresentations ?? ['distance', 'travelTime']) {\n urlParams.append('extendedRouteRepresentation', representation);\n }\n\n const postData = buildPostData(params, routePlanningLocationTypes, useEntryPoints);\n return postData ? { method: 'POST', url, data: postData } : { method: 'GET', url };\n};\n","import {\n BBox,\n bboxFromGeoJSON,\n type ChargingStop,\n type CountrySectionProps,\n type CurrentType,\n type Guidance,\n generateId,\n type ImportantRoadStretchProps,\n type Instruction,\n indexedMagnitudes,\n type LaneDirection,\n type LaneSectionProps,\n type LegSectionProps,\n type LegSummary,\n type PossibleLaneSeparator,\n type RoadShieldReference,\n type RoadShieldSectionProps,\n type Route,\n type RouteSummary,\n type Routes,\n type SectionProps,\n type SectionsProps,\n type SectionType,\n type SpeedLimitSectionProps,\n type TrafficIncidentCategory,\n type TrafficIncidentTEC,\n type TrafficSectionProps,\n} from '@tomtom-org/maps-sdk/core';\nimport type { LineString, Position } from 'geojson';\nimport { isNil, omit } from 'lodash-es';\nimport { toChargingSpeed } from '../shared/ev';\nimport { ExplicitVehicleModel } from '../shared/types/vehicleModel';\nimport {\n CalculateRouteResponseAPI,\n ChargingStopAPI,\n CurrentTypeAPI,\n GuidanceAPI,\n LegAPI,\n RouteAPI,\n RoutePathPointAPI,\n SectionAPI,\n SummaryAPI,\n} from './types/apiResponseTypes';\nimport { CalculateRouteParams } from './types/calculateRouteParams';\n\nconst toCurrentType = (apiCurrentType: CurrentTypeAPI): CurrentType | undefined => {\n switch (apiCurrentType) {\n case 'Direct_Current':\n return 'DC';\n case 'Alternating_Current_1_Phase':\n return 'AC1';\n case 'Alternating_Current_3_Phase':\n return 'AC3';\n default:\n return undefined;\n }\n};\n\nconst toChargingStop = (\n chargingInformationAtEndOfLeg: ChargingStopAPI,\n maxChargeKWH: number | undefined,\n): ChargingStop => {\n const chargingConnectionInfo = chargingInformationAtEndOfLeg.chargingConnectionInfo;\n const chargingParkLocation = chargingInformationAtEndOfLeg.chargingParkLocation;\n const coordinates = [chargingParkLocation.coordinate.longitude, chargingParkLocation.coordinate.latitude];\n\n // Build freeformAddress from available components\n const addressParts = [chargingParkLocation.street, chargingParkLocation.houseNumber].filter(Boolean);\n const freeformAddress = addressParts.length > 0 ? addressParts.join(', ') : '';\n\n return {\n type: 'Feature',\n id: chargingInformationAtEndOfLeg.chargingParkId,\n geometry: { type: 'Point', coordinates },\n properties: {\n ...omit(chargingInformationAtEndOfLeg, ['chargingConnectionInfo', 'chargingParkLocation']),\n type: 'POI',\n address: {\n freeformAddress,\n ...(chargingParkLocation.street && { streetName: chargingParkLocation.street }),\n ...(chargingParkLocation.houseNumber && { streetNumber: chargingParkLocation.houseNumber }),\n ...(chargingParkLocation.city && { municipality: chargingParkLocation.city }),\n ...(chargingParkLocation.region && { countrySubdivision: chargingParkLocation.region }),\n ...(chargingParkLocation.postalCode && { postalCode: chargingParkLocation.postalCode }),\n ...(chargingParkLocation.country && { country: chargingParkLocation.country }),\n },\n ...(chargingConnectionInfo && {\n chargingConnectionInfo: {\n plugType: chargingConnectionInfo.chargingPlugType,\n currentInA: chargingConnectionInfo.chargingCurrentInA,\n voltageInV: chargingConnectionInfo.chargingVoltageInV,\n chargingPowerInkW: chargingConnectionInfo.chargingPowerInkW,\n currentType: toCurrentType(chargingConnectionInfo.chargingCurrentType),\n chargingSpeed: toChargingSpeed(chargingConnectionInfo.chargingPowerInkW),\n },\n }),\n ...(maxChargeKWH && {\n targetChargeInPCT: (100 * chargingInformationAtEndOfLeg.targetChargeInkWh) / maxChargeKWH,\n }),\n ...(chargingInformationAtEndOfLeg.chargingParkPowerInkW && {\n chargingParkSpeed: toChargingSpeed(chargingInformationAtEndOfLeg.chargingParkPowerInkW),\n }),\n },\n };\n};\n\nconst parseSummary = (apiSummary: SummaryAPI, params: CalculateRouteParams): RouteSummary | LegSummary => {\n const maxChargeKWH = (params?.vehicle?.model as ExplicitVehicleModel<'electric'>)?.engine?.charging?.maxChargeKWH;\n return {\n lengthInMeters: apiSummary.lengthInMeters,\n historicTrafficTravelTimeInSeconds: apiSummary.historicTrafficTravelTimeInSeconds,\n liveTrafficIncidentsTravelTimeInSeconds: apiSummary.liveTrafficIncidentsTravelTimeInSeconds,\n noTrafficTravelTimeInSeconds: apiSummary.noTrafficTravelTimeInSeconds,\n trafficDelayInSeconds: apiSummary.trafficDelayInSeconds,\n trafficLengthInMeters: apiSummary.trafficLengthInMeters,\n travelTimeInSeconds: apiSummary.travelTimeInSeconds,\n departureTime: new Date(apiSummary.departureTime),\n arrivalTime: new Date(apiSummary.arrivalTime),\n deviationDistanceInMeters: apiSummary.deviationDistance,\n fuelConsumptionInLiters: apiSummary.fuelConsumptionInLiters,\n ...(apiSummary.deviationPoint && {\n deviationPoint: [apiSummary.deviationPoint.longitude, apiSummary.deviationPoint.latitude],\n }),\n // EV-specific fields:\n totalChargingTimeInSeconds: apiSummary.totalChargingTimeInSeconds,\n batteryConsumptionInkWh: apiSummary.batteryConsumptionInkWh,\n ...(maxChargeKWH &&\n apiSummary.batteryConsumptionInkWh && {\n batteryConsumptionInPCT: (100 * apiSummary.batteryConsumptionInkWh) / maxChargeKWH,\n }),\n remainingChargeAtArrivalInkWh: apiSummary.remainingChargeAtArrivalInkWh,\n ...(maxChargeKWH &&\n apiSummary.remainingChargeAtArrivalInkWh && {\n remainingChargeAtArrivalInPCT: (100 * apiSummary.remainingChargeAtArrivalInkWh) / maxChargeKWH,\n }),\n ...(apiSummary.chargingInformationAtEndOfLeg && {\n chargingInformationAtEndOfLeg: toChargingStop(apiSummary.chargingInformationAtEndOfLeg, maxChargeKWH),\n }),\n };\n};\n\nconst parseRoutePath = (apiRouteLegs: LegAPI[]): LineString => ({\n type: 'LineString',\n coordinates: apiRouteLegs.flatMap((apiLeg) =>\n apiLeg.points?.map((apiPoint) => [apiPoint.longitude, apiPoint.latitude]),\n ),\n});\n\nconst parseLegSectionProps = (apiLegs: LegAPI[], params: CalculateRouteParams): LegSectionProps[] =>\n apiLegs.reduce<LegSectionProps[]>((accumulatedParsedLegs, nextApiLeg, currentIndex) => {\n const lastLegEndPointIndex = currentIndex === 0 ? 0 : accumulatedParsedLegs[currentIndex - 1]?.endPointIndex;\n let endPointIndex;\n if (!isNil(lastLegEndPointIndex)) {\n if (lastLegEndPointIndex === 0) {\n // in case of first or only leg, we reduce the length by one to be consistent with other sections\n // endPointIndex is inclusive\n endPointIndex = nextApiLeg.points?.length > 0 ? nextApiLeg.points.length - 1 : 0;\n } else {\n endPointIndex = lastLegEndPointIndex + nextApiLeg.points?.length;\n }\n }\n accumulatedParsedLegs.push({\n ...(!isNil(lastLegEndPointIndex) && { startPointIndex: lastLegEndPointIndex }),\n ...(endPointIndex && { endPointIndex }),\n summary: parseSummary(nextApiLeg.summary, params),\n id: generateId(),\n });\n return accumulatedParsedLegs;\n }, []);\n\nconst toSectionProps = (apiSection: SectionAPI): SectionProps => ({\n id: generateId(),\n startPointIndex: apiSection.startPointIndex,\n endPointIndex: apiSection.endPointIndex,\n});\n\nconst toRoadStretchSectionProps = (apiSection: SectionAPI): ImportantRoadStretchProps => ({\n ...toSectionProps(apiSection),\n index: apiSection.importantRoadStretchIndex as number,\n streetName: apiSection.streetName?.text,\n roadNumbers: apiSection.roadNumbers?.map((roadNumber) => roadNumber.text),\n});\n\nconst toCountrySectionProps = (apiSection: SectionAPI): CountrySectionProps => ({\n ...toSectionProps(apiSection),\n countryCodeISO3: apiSection.countryCode as string,\n});\n\nconst toVehicleRestrictedSectionProps = (apiSection: SectionAPI): SectionProps | null =>\n apiSection.travelMode === 'other' ? toSectionProps(apiSection) : null;\n\nconst calculateTrafficCategory = (tecMainCauseCode: number | undefined): TrafficIncidentCategory => {\n switch (tecMainCauseCode) {\n case 1:\n return 'jam';\n case 2:\n return 'accident';\n case 3:\n return 'roadworks';\n case 4:\n return 'narrow-lanes';\n case 5:\n return 'road-closed';\n case 9:\n return 'danger';\n case 11:\n return 'animals-on-road';\n case 13:\n return 'broken-down-vehicle';\n case 16:\n return 'lane-closed';\n case 17:\n return 'wind';\n case 18:\n return 'fog';\n case 19:\n return 'rain';\n case 22:\n return 'frost';\n case 23:\n return 'flooding';\n default:\n return 'other';\n }\n};\n\n/**\n * @ignore\n */\nexport const toTrafficCategories = (apiSection: SectionAPI): TrafficIncidentCategory[] => {\n if (apiSection.tec?.causes?.length) {\n return apiSection.tec.causes.map((cause) => calculateTrafficCategory(cause.mainCauseCode));\n }\n // else\n switch (apiSection.simpleCategory) {\n case 'JAM':\n return ['jam'];\n case 'ROAD_WORK':\n return ['roadworks'];\n case 'ROAD_CLOSURE':\n return ['road-closed'];\n default:\n return ['other'];\n }\n};\n\nconst toTrafficSectionProps = (apiSection: SectionAPI): TrafficSectionProps => ({\n ...toSectionProps(apiSection),\n delayInSeconds: apiSection.delayInSeconds,\n effectiveSpeedInKmh: apiSection.effectiveSpeedInKmh,\n categories: toTrafficCategories(apiSection),\n magnitudeOfDelay: indexedMagnitudes[apiSection.magnitudeOfDelay as number],\n tec: apiSection.tec as TrafficIncidentTEC,\n});\n\nconst toLaneSectionProps = (apiSection: SectionAPI): LaneSectionProps => ({\n ...toSectionProps(apiSection),\n lanes: apiSection.lanes as LaneDirection[],\n laneSeparators: apiSection.laneSeparators as PossibleLaneSeparator[],\n properties: apiSection.properties,\n});\n\nconst toSpeedLimitSectionProps = (apiSection: SectionAPI): SpeedLimitSectionProps => ({\n ...toSectionProps(apiSection),\n maxSpeedLimitInKmh: apiSection.maxSpeedLimitInKmh as number,\n});\n\nconst toRoadShieldsSectionProps = (apiSection: SectionAPI): RoadShieldSectionProps => ({\n ...toSectionProps(apiSection),\n roadShieldReferences: apiSection.roadShieldReferences as RoadShieldReference[],\n});\n\nconst ensureInit = <S extends SectionProps>(sectionType: SectionType, result: SectionsProps): S[] => {\n if (!result[sectionType]) {\n result[sectionType] = [];\n }\n return result[sectionType] as S[];\n};\n\nconst getSectionMapping = (\n apiSection: SectionAPI,\n): { sectionType: SectionType; mappingFunction: (apiSection: SectionAPI) => SectionProps | null } => {\n switch (apiSection.sectionType) {\n case 'CAR_TRAIN':\n return { sectionType: 'carTrain', mappingFunction: toSectionProps };\n case 'COUNTRY':\n return { sectionType: 'country', mappingFunction: toCountrySectionProps };\n case 'FERRY':\n return { sectionType: 'ferry', mappingFunction: toSectionProps };\n case 'MOTORWAY':\n return { sectionType: 'motorway', mappingFunction: toSectionProps };\n case 'PEDESTRIAN':\n return { sectionType: 'pedestrian', mappingFunction: toSectionProps };\n case 'TOLL_VIGNETTE':\n return { sectionType: 'tollVignette', mappingFunction: toCountrySectionProps };\n case 'TOLL':\n return { sectionType: 'toll', mappingFunction: toSectionProps };\n case 'TRAFFIC':\n return { sectionType: 'traffic', mappingFunction: toTrafficSectionProps };\n case 'TRAVEL_MODE':\n // NOTE: vehicleRestricted sections come from TRAVEL_MODE \"other\" ones:\n return { sectionType: 'vehicleRestricted', mappingFunction: toVehicleRestrictedSectionProps };\n case 'TUNNEL':\n return { sectionType: 'tunnel', mappingFunction: toSectionProps };\n case 'UNPAVED':\n return { sectionType: 'unpaved', mappingFunction: toSectionProps };\n case 'URBAN':\n return { sectionType: 'urban', mappingFunction: toSectionProps };\n case 'CARPOOL':\n return { sectionType: 'carpool', mappingFunction: toSectionProps };\n case 'LOW_EMISSION_ZONE':\n return { sectionType: 'lowEmissionZone', mappingFunction: toSectionProps };\n case 'LANES':\n return { sectionType: 'lanes', mappingFunction: toLaneSectionProps };\n case 'SPEED_LIMIT':\n return { sectionType: 'speedLimit', mappingFunction: toSpeedLimitSectionProps };\n case 'ROAD_SHIELDS':\n return { sectionType: 'roadShields', mappingFunction: toRoadShieldsSectionProps };\n case 'IMPORTANT_ROAD_STRETCH':\n return { sectionType: 'importantRoadStretch', mappingFunction: toRoadStretchSectionProps };\n }\n};\n\nconst parseSectionsAndAppendToResult = (apiSections: SectionAPI[], result: SectionsProps): void => {\n if (!Array.isArray(apiSections)) {\n return;\n }\n\n for (const apiSection of apiSections) {\n const sectionMapping = getSectionMapping(apiSection);\n const mappedSection = sectionMapping?.mappingFunction(apiSection);\n if (mappedSection) {\n ensureInit(sectionMapping.sectionType, result).push(mappedSection);\n }\n }\n};\n\nconst parseSections = (apiRoute: RouteAPI, params: CalculateRouteParams): SectionsProps => {\n const result = {\n leg: parseLegSectionProps(apiRoute.legs, params),\n // (the rest of sections are parsed below)\n } as SectionsProps;\n parseSectionsAndAppendToResult(apiRoute.sections, result);\n return result;\n};\n\nconst DELTA = 0.0001;\n\nconst similar = (a: Position, b: Position): boolean => Math.abs(a[0] - b[0]) < DELTA && Math.abs(a[1] - b[1]) < DELTA;\n\nconst parseGuidance = (apiGuidance: GuidanceAPI, path: Position[]): Guidance => {\n const instructions: Instruction[] = [];\n let lastInstructionPathIndex = 0;\n\n for (const apiInstruction of apiGuidance.instructions) {\n const maneuverPoint = [apiInstruction.maneuverPoint.longitude, apiInstruction.maneuverPoint.latitude];\n\n // we determine the path point index for the instruction by matching maneuverPoint to the path:\n for (let pathIndex = lastInstructionPathIndex; pathIndex < path.length; pathIndex++) {\n if (similar(path[pathIndex], maneuverPoint)) {\n lastInstructionPathIndex = pathIndex;\n break;\n }\n if (pathIndex === path.length - 1) {\n // (we do not advance lastInstructionPathIndex here to prevent missing a whole path section while mapping following instructions)\n break;\n }\n }\n instructions.push({\n ...apiInstruction,\n maneuverPoint,\n pathPointIndex: lastInstructionPathIndex,\n routePath: apiInstruction.routePath.map((apiPoint: RoutePathPointAPI) => ({\n ...apiPoint,\n point: [apiPoint.point.longitude, apiPoint.point.latitude],\n })),\n });\n }\n\n return { instructions };\n};\n\nconst parseRoute = (apiRoute: RouteAPI, index: number, params: CalculateRouteParams): Route => {\n const geometry = parseRoutePath(apiRoute.legs);\n return {\n type: 'Feature',\n geometry,\n id: generateId(),\n bbox: bboxFromGeoJSON(geometry) as BBox, // Route geometry should always have area\n properties: {\n index,\n summary: parseSummary(apiRoute.summary, params),\n sections: parseSections(apiRoute, params),\n ...(apiRoute.guidance && { guidance: parseGuidance(apiRoute.guidance, geometry.coordinates) }),\n ...(apiRoute.progress && { progress: apiRoute.progress }),\n },\n };\n};\n\n/**\n * Default method for parsing calculate route response from {@link CalculateRouteResponseAPI}\n * @param apiResponse The Routing API response.\n * @param params The params used to calculate this route.\n */\nexport const parseCalculateRouteResponse = (\n apiResponse: CalculateRouteResponseAPI,\n params: CalculateRouteParams,\n): Routes => {\n const features = apiResponse.routes.map((apiRoute, index) => parseRoute(apiRoute, index, params));\n const bbox = bboxFromGeoJSON(features);\n return { type: 'FeatureCollection', ...(bbox && { bbox }), features };\n};\n","import type { Routes } from '@tomtom-org/maps-sdk/core';\nimport type { FetchInput, ServiceTemplate } from '../shared';\nimport { fetchWith } from '../shared/fetch';\nimport { routeRequestValidationConfig } from './calculateRouteRequestSchema';\nimport { buildCalculateRouteRequest } from './requestBuilder';\nimport { parseCalculateRouteResponse } from './responseParser';\nimport { parseRoutingResponseError } from './routingResponseErrorParser';\nimport type { CalculateRoutePOSTDataAPI } from './types/apiRequestTypes';\nimport type { CalculateRouteResponseAPI } from './types/apiResponseTypes';\nimport type { CalculateRouteParams } from './types/calculateRouteParams';\n\n/**\n * @ignore\n */\nexport type CalculateRouteTemplate = ServiceTemplate<\n CalculateRouteParams,\n FetchInput<CalculateRoutePOSTDataAPI>,\n CalculateRouteResponseAPI,\n Routes\n>;\n\n/**\n * @ignore\n */\nexport const calculateRouteTemplate: CalculateRouteTemplate = {\n requestValidation: routeRequestValidationConfig,\n buildRequest: buildCalculateRouteRequest,\n sendRequest: fetchWith,\n parseResponse: parseCalculateRouteResponse,\n parseResponseError: parseRoutingResponseError,\n getAPIVersion: () => 2,\n};\n","import type { CalculateRouteTemplate } from './calculateRouteTemplate';\nimport { calculateRouteTemplate } from './calculateRouteTemplate';\nimport { buildCalculateRouteRequest } from './requestBuilder';\nimport { parseCalculateRouteResponse } from './responseParser';\n\nconst customize: {\n buildCalculateRouteRequest: typeof buildCalculateRouteRequest;\n parseCalculateRouteResponse: typeof parseCalculateRouteResponse;\n calculateRouteTemplate: CalculateRouteTemplate;\n} = {\n buildCalculateRouteRequest,\n parseCalculateRouteResponse,\n calculateRouteTemplate,\n};\nexport default customize;\n","import { bboxFromGeoJSON, trafficIncidentToIconCategory } from '@tomtom-org/maps-sdk/core';\nimport type { FetchInput } from '../shared';\nimport {\n appendByJoiningParamValue,\n appendCommonParams,\n appendOptionalParam,\n} from '../shared/request/requestBuildingUtils';\nimport type { TrafficIncidentDetailsParams } from './types/trafficIncidentDetailsParams';\n\nconst TRAFFIC_URL_PATH = '/maps/orbis/traffic';\n\n// Request all available incident fields by default so callers get a complete response without\n// having to manually specify a projection string.\nconst DEFAULT_FIELDS =\n '{incidents{type,geometry{type,coordinates},properties{id,iconCategory,magnitudeOfDelay,events{description,code,iconCategory},startTime,endTime,from,to,length,delay,roadNumbers,timeValidity,probabilityOfOccurrence,numberOfReports,lastReportTime,tmc{countryCode,tableNumber,tableVersion,direction,points{location,offset}}}}}';\n\ntype TrafficIncidentDetailsPostBody = { ids: string[] };\n\nconst buildUrlBasePath = (params: TrafficIncidentDetailsParams): string =>\n params.customServiceBaseURL ?? `${params.commonBaseURL}${TRAFFIC_URL_PATH}/incidentDetails`;\n\nconst appendOptionalParams = (urlParams: URLSearchParams, params: TrafficIncidentDetailsParams): void => {\n appendOptionalParam(urlParams, 'fields', DEFAULT_FIELDS);\n appendOptionalParam(urlParams, 't', params.trafficModelId);\n appendByJoiningParamValue(urlParams, 'categoryFilter', params.categoryFilter?.map(trafficIncidentToIconCategory));\n appendByJoiningParamValue(urlParams, 'timeValidityFilter', params.timeValidityFilter);\n};\n\n/**\n * Default method for building a traffic incident details request from {@link TrafficIncidentDetailsParams}.\n * @param params The traffic incident details parameters, with global configuration already merged into them.\n */\nexport const buildTrafficIncidentDetailsRequest = (\n params: TrafficIncidentDetailsParams,\n): FetchInput<TrafficIncidentDetailsPostBody> => {\n const url = new URL(buildUrlBasePath(params));\n const urlParams = url.searchParams;\n appendCommonParams(urlParams, params);\n appendOptionalParams(urlParams, params);\n\n if ('bbox' in params && params.bbox) {\n const resolvedBBox = bboxFromGeoJSON(params.bbox);\n if (resolvedBBox) {\n urlParams.append('bbox', resolvedBBox.join(','));\n }\n return { method: 'GET', url };\n }\n\n // ids-based request — POST when there are more than 5 IDs (GET limit), GET otherwise\n const { ids } = params as { ids: string[] };\n\n if (ids.length > 5) {\n return { method: 'POST', url, data: { ids } };\n }\n\n urlParams.append('ids', ids.join(','));\n return { method: 'GET', url };\n};\n","import {\n iconToTrafficIncidentCategory,\n indexedMagnitudes,\n type TrafficIncident,\n type TrafficIncidentDetails,\n type TrafficIncidentEvent,\n type TrafficIncidentProbability,\n type TrafficIncidentTimeValidity,\n type TrafficIncidentTMC,\n} from '@tomtom-org/maps-sdk/core';\nimport type { IncidentAPI, IncidentDetailsResponseAPI, IncidentEventAPI, IncidentTMCAPI } from './types/apiTypes';\n\nconst parseEvent = (apiEvent: IncidentEventAPI): TrafficIncidentEvent => ({\n description: apiEvent.description,\n code: apiEvent.code,\n category: iconToTrafficIncidentCategory(apiEvent.iconCategory),\n});\n\nconst parseTMC = (apiTMC: IncidentTMCAPI): TrafficIncidentTMC => ({\n countryCode: apiTMC.countryCode,\n tableNumber: apiTMC.tableNumber,\n tableVersion: apiTMC.tableVersion,\n direction: apiTMC.direction as 'positive' | 'negative',\n points: (apiTMC.points ?? []).map((p) => ({\n location: p.location,\n ...(p.offset !== undefined && { offset: p.offset }),\n })),\n});\n\nconst parseIncident = (apiIncident: IncidentAPI): TrafficIncident => {\n const p = apiIncident.properties;\n return {\n type: 'Feature',\n geometry: apiIncident.geometry,\n properties: {\n id: p.id,\n category: iconToTrafficIncidentCategory(p.iconCategory),\n magnitudeOfDelay: indexedMagnitudes[p.magnitudeOfDelay] ?? 'unknown',\n events: (p.events ?? []).map(parseEvent),\n ...(p.startTime && { startTime: new Date(p.startTime) }),\n ...(p.endTime && { endTime: new Date(p.endTime) }),\n ...(p.from && { from: p.from }),\n ...(p.to && { to: p.to }),\n ...(p.length !== undefined && { lengthInMeters: p.length }),\n ...(p.delay !== undefined && { delayInSeconds: p.delay }),\n ...(p.roadNumbers && { roadNumbers: p.roadNumbers }),\n timeValidity: p.timeValidity as TrafficIncidentTimeValidity,\n ...(p.probabilityOfOccurrence && {\n probabilityOfOccurrence: p.probabilityOfOccurrence as TrafficIncidentProbability,\n }),\n ...(p.numberOfReports !== undefined && { numberOfReports: p.numberOfReports }),\n ...(p.lastReportTime && { lastReportTime: new Date(p.lastReportTime) }),\n ...(p.tmc && { tmc: parseTMC(p.tmc) }),\n },\n };\n};\n\n/**\n * Default method for parsing a traffic incident details API response.\n * @param apiResponse The raw Traffic Incident Details API response.\n */\nexport const parseTrafficIncidentDetailsResponse = (\n apiResponse: IncidentDetailsResponseAPI,\n): TrafficIncidentDetails => ({\n type: 'FeatureCollection',\n features: (apiResponse.incidents ?? []).filter((i): i is IncidentAPI => i !== null).map(parseIncident),\n});\n","import type { TrafficIncidentDetails } from '@tomtom-org/maps-sdk/core';\nimport type { FetchInput, ServiceTemplate } from '../shared';\nimport { fetchWith } from '../shared/fetch';\nimport { buildTrafficIncidentDetailsRequest } from './requestBuilder';\nimport { parseTrafficIncidentDetailsResponse } from './responseParser';\nimport { trafficIncidentDetailsRequestSchema } from './trafficIncidentDetailsRequestSchema';\nimport type { IncidentDetailsResponseAPI } from './types/apiTypes';\nimport type { TrafficIncidentDetailsParams } from './types/trafficIncidentDetailsParams';\n\ntype TrafficIncidentDetailsPostBody = { ids: string[] };\n\n/**\n * Traffic Incident Details service template type.\n * @ignore\n */\nexport type TrafficIncidentDetailsTemplate = ServiceTemplate<\n TrafficIncidentDetailsParams,\n FetchInput<TrafficIncidentDetailsPostBody>,\n IncidentDetailsResponseAPI,\n TrafficIncidentDetails\n>;\n\n/**\n * Traffic Incident Details service template main implementation.\n * @ignore\n */\nexport const trafficIncidentDetailsTemplate: TrafficIncidentDetailsTemplate = {\n requestValidation: { schema: trafficIncidentDetailsRequestSchema },\n buildRequest: buildTrafficIncidentDetailsRequest,\n sendRequest: fetchWith,\n parseResponse: parseTrafficIncidentDetailsResponse,\n};\n","import { trafficIncidentCategories } from '@tomtom-org/maps-sdk/core';\nimport { z } from 'zod';\nimport { commonServiceRequestSchema } from '../shared/schema/commonParamsSchema';\nimport { hasBBoxSchema } from '../shared/schema/geometriesSchema';\n\n/**\n * @ignore\n */\nexport const trafficIncidentDetailsRequestSchema = commonServiceRequestSchema\n .extend({\n bbox: hasBBoxSchema.optional(),\n ids: z.array(z.string()).optional().describe('List of incident IDs'),\n trafficModelId: z.string().optional().describe('Traffic Model ID for temporal consistency'),\n categoryFilter: z\n .array(z.enum([...trafficIncidentCategories]))\n .optional()\n .describe('Incident category filter'),\n timeValidityFilter: z\n .array(z.enum(['present', 'future']))\n .optional()\n .describe('Time validity filter'),\n })\n .refine((data) => !(data.bbox && data.ids), {\n message: 'Provide either bbox or ids, not both',\n });\n","/**\n * @module services-customization\n * @group Customization\n */\n\nimport autocompleteCustomize from '../autocomplete-search/customize';\nimport evChargingStationsAvailabilityCustomize from '../ev-charging-stations-availability/customize';\nimport geocodeCustomize from '../geocode/customize';\nimport geometryDataCustomize from '../geometry-data/customize';\nimport geometrySearchCustomize from '../geometry-search/customize';\nimport placeByIdCustomize from '../place-by-id/customize';\nimport reachableRangeCustomize from '../reachable-range/customize';\nimport revgeoCustomize from '../revgeo/customize';\nimport routingCustomize from '../routing/customize';\nimport trafficIncidentDetailsCustomize from '../traffic-incident-details/customize';\n\n/**\n * Access to service implementation components for advanced customization.\n *\n * This object provides low-level access to the internal components of each service,\n * allowing developers to customize request building, response parsing, and other\n * aspects of service behavior. This is useful for advanced use cases like:\n * - Custom request/response transformations\n * - Integration with custom API gateways or proxies\n * - Adding custom validation or error handling\n * - Implementing request/response logging or monitoring\n * - Adapting to custom API endpoints or versions\n *\n * @remarks\n * Most developers won't need to use this directly. The standard service functions\n * (like `geocode`, `search`, `calculateRoute`) are sufficient for typical use cases.\n * Only use customization when you need to modify the internal service behavior.\n *\n * Each service exposes:\n * - Request builders: Functions that construct API requests\n * - Response parsers: Functions that transform API responses\n * - Templates: Configuration objects defining service behavior\n * - Validation schemas: Input parameter validation rules\n *\n * @example\n * ```typescript\n * // Access request builder for custom processing\n * import { customizeService } from '@tomtom-international/web-sdk-services';\n *\n * const { buildRequest } = customizeService.geocode;\n * const request = buildRequest({\n * key: 'your-api-key',\n * query: 'Amsterdam'\n * });\n *\n * // Access response parser for custom handling\n * const { parseResponse } = customizeService.geocode;\n * const rawApiResponse = await fetch(request.url);\n * const parsedData = parseResponse(await rawApiResponse.json());\n * ```\n *\n * @group Advanced\n */\nexport const customizeService: {\n reverseGeocode: typeof revgeoCustomize;\n geocode: typeof geocodeCustomize;\n geometryData: typeof geometryDataCustomize;\n geometrySearch: typeof geometrySearchCustomize;\n calculateRoute: typeof routingCustomize;\n reachableRange: typeof reachableRangeCustomize;\n evChargingStationsAvailability: typeof evChargingStationsAvailabilityCustomize;\n trafficIncidentDetails: typeof trafficIncidentDetailsCustomize;\n placeByID: typeof placeByIdCustomize;\n autocompleteSearch: typeof autocompleteCustomize;\n} = {\n reverseGeocode: revgeoCustomize,\n geocode: geocodeCustomize,\n geometryData: geometryDataCustomize,\n geometrySearch: geometrySearchCustomize,\n calculateRoute: routingCustomize,\n reachableRange: reachableRangeCustomize,\n evChargingStationsAvailability: evChargingStationsAvailabilityCustomize,\n trafficIncidentDetails: trafficIncidentDetailsCustomize,\n placeByID: placeByIdCustomize,\n autocompleteSearch: autocompleteCustomize,\n};\n","import { buildTrafficIncidentDetailsRequest } from './requestBuilder';\nimport { parseTrafficIncidentDetailsResponse } from './responseParser';\nimport type { TrafficIncidentDetailsTemplate } from './trafficIncidentDetailsTemplate';\nimport { trafficIncidentDetailsTemplate } from './trafficIncidentDetailsTemplate';\n\nconst customize: {\n buildTrafficIncidentDetailsRequest: typeof buildTrafficIncidentDetailsRequest;\n parseTrafficIncidentDetailsResponse: typeof parseTrafficIncidentDetailsResponse;\n trafficIncidentDetailsTemplate: TrafficIncidentDetailsTemplate;\n} = {\n buildTrafficIncidentDetailsRequest,\n parseTrafficIncidentDetailsResponse,\n trafficIncidentDetailsTemplate,\n};\nexport default customize;\n","import type {\n ChargingPark,\n ChargingParkWithAvailability,\n ChargingStationsAvailability,\n CommonPlaceProps,\n EVChargingStationWithAvailabilityPlaceProps,\n Place,\n Places,\n} from '@tomtom-org/maps-sdk/core';\nimport { bboxFromGeoJSON } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { EVChargingStationsAvailabilityTemplate } from './evChargingStationsAvailabilityTemplate';\nimport { evChargingStationsAvailabilityTemplate } from './evChargingStationsAvailabilityTemplate';\nimport type { ChargingStationsAvailabilityParams } from './types/evChargingStationsAvailabilityParams';\n\n/**\n * Get real-time availability of electric vehicle charging stations.\n *\n * Provides current operational status of charging points and connectors at EV charging parks,\n * enabling drivers to find available chargers before arriving at a location.\n *\n * @remarks\n * Key information returned:\n * - **Point-level status**: Available, Occupied, Reserved, Out of Service\n * - **Connector details**: Power ratings, plug types, current availability\n * - **Aggregated counts**: Quick overview of available vs occupied chargers\n * - **Access information**: Public, private, or restricted access\n * - **Opening hours**: When the charging facility is accessible\n *\n * @param params - Charging availability parameters with station ID\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to charging station availability information\n *\n * @example\n * ```typescript\n * // Get availability for a specific charging park\n * const availability = await evChargingStationsAvailability({\n * key: 'your-api-key',\n * id: 'charging-park-id-123'\n * });\n *\n * // Check how many chargers are available\n * const availableCount = availability.chargingPointAvailability.statusCounts.Available;\n * console.log(`${availableCount} chargers available`);\n *\n * // Find available CCS connectors\n * const ccsConnectors = availability.connectorAvailabilities.find(\n * ca => ca.connector.type === 'IEC62196Type2CCS'\n * );\n * ```\n *\n * @see [EV Charging Availability API](https://docs.tomtom.com/search-api/documentation)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [EV Charging Stations Availability Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/ev-charging-stations-availability)\n *\n * @group EV Charging\n */\nexport const evChargingStationsAvailability = async (\n params: ChargingStationsAvailabilityParams,\n customTemplate?: Partial<EVChargingStationsAvailabilityTemplate>,\n): Promise<ChargingStationsAvailability | undefined> =>\n callService(\n params,\n { ...evChargingStationsAvailabilityTemplate, ...customTemplate },\n 'EVChargingStationsAvailability',\n );\n\n/**\n * Enhance a place with real-time EV charging availability data.\n *\n * Fetches availability information for an EV charging station and merges it into\n * the place properties.\n *\n * @param place - The place to enhance with availability data\n *\n * @returns Promise resolving to the place with merged availability information\n * @returns undefined if no availability data is present for the `place` input parameter.\n *\n * @example\n * ```typescript\n * // After search, enhance place with availability\n * const searchResult = await search({ query: 'EV charging', ... });\n * const place = searchResult.features[0];\n *\n * const enhancedPlace = await getPlaceWithEVAvailability(place);\n * const availability = enhancedPlace.properties.chargingPark?.availability;\n *\n * if (availability) {\n * console.log('Available chargers:', availability.chargingPointAvailability.count);\n * }\n * ```\n *\n * @group EV Charging\n */\nexport const getPlaceWithEVAvailability = async <P extends CommonPlaceProps = CommonPlaceProps>(\n place: Place<P>,\n): Promise<Place<EVChargingStationWithAvailabilityPlaceProps> | undefined> => {\n const availabilityId = place.properties.dataSources?.chargingAvailability?.id;\n if (!availabilityId) {\n return undefined;\n }\n try {\n const availability = await evChargingStationsAvailability({ id: availabilityId });\n const poi = place.properties.poi;\n return availability\n ? {\n ...place,\n properties: {\n ...place.properties,\n // We override poi opening hours with the ones from the EV call, which might be better supported:\n ...(poi && { poi: { ...poi, openingHours: availability.openingHours } }),\n chargingPark: {\n ...(place.properties.chargingPark as ChargingPark),\n availability,\n },\n },\n }\n : undefined;\n } catch (e) {\n // (Likely a QPS limit error)\n console.error(e);\n return undefined;\n }\n};\n\n/**\n * Enhance multiple places with real-time EV charging availability data.\n *\n * Fetches availability information for all EV charging stations in a collection\n * and merges it into their properties. Non-EV places and EV stations without availability data are returned unchanged.\n *\n * @remarks\n * **Important**: Availability requests are made sequentially to avoid exceeding\n * API rate limits (QPS - Queries Per Second). For large result sets, this may\n * take some time.\n *\n * @param places - Collection of places to enhance\n * @param options - Configuration options\n *\n * @returns Promise resolving to places collection with merged availability\n *\n * @example\n * ```typescript\n * // Search for charging stations and add availability\n * const results = await search({\n * query: 'EV charging',\n * at: [4.9, 52.3],\n * radius: 5000\n * });\n *\n * const withAvailability = await getPlacesWithEVAvailability(results, {\n * excludeIfAvailabilityUnknown: true // Filter out stations with unknown availability\n * });\n *\n * // Display only stations with known availability\n * withAvailability.features.forEach(place => {\n * const available = place.properties.chargingPark?.availability?.chargingPointAvailability.count;\n * console.log(`${place.properties.poi?.name}: ${available} chargers`);\n * });\n * ```\n *\n * @group EV Charging\n */\nexport async function getPlacesWithEVAvailability<P extends CommonPlaceProps = CommonPlaceProps>(\n places: Places<P>,\n options?: {\n excludeIfAvailabilityUnknown: true;\n },\n): Promise<Places<EVChargingStationWithAvailabilityPlaceProps>>;\n\nexport async function getPlacesWithEVAvailability<P extends CommonPlaceProps = CommonPlaceProps>(\n places: Places<P>,\n options?: {\n /**\n * If true, places with unknown availability will be filtered out. Otherwise, they will be included.\n * @default false\n */\n excludeIfAvailabilityUnknown?: boolean;\n },\n): Promise<Places<P | EVChargingStationWithAvailabilityPlaceProps>> {\n const enhancedPlaces: Array<Place<P> | Place<EVChargingStationWithAvailabilityPlaceProps>> = [];\n for (const place of places.features) {\n // (We fetch the availabilities sequentially on purpose to prevent QPS limit errors)\n const placeWithAvailability = await getPlaceWithEVAvailability(place);\n if (placeWithAvailability) {\n enhancedPlaces.push(placeWithAvailability);\n } else if (!options?.excludeIfAvailabilityUnknown) {\n enhancedPlaces.push(place);\n }\n }\n return { ...places, features: enhancedPlaces, bbox: bboxFromGeoJSON(enhancedPlaces) };\n}\n\n/**\n * Type guard to check if a ChargingPark has availability data.\n *\n * @param chargingPark - The charging park to check\n * @returns True if the charging park has availability data\n *\n * @group EV Charging\n */\nexport const hasChargingAvailability = (\n chargingPark: ChargingPark | ChargingParkWithAvailability | undefined,\n): chargingPark is ChargingParkWithAvailability =>\n Boolean(chargingPark && 'availability' in chargingPark && chargingPark.availability);\n\nexport default evChargingStationsAvailability;\n","import type { Place } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { GeocodingTemplate } from './geocodingTemplate';\nimport { geocodingTemplate } from './geocodingTemplate';\nimport type { GeocodingParams } from './types/geocodingParams';\nimport type { GeocodingProps, GeocodingResponse } from './types/geocodingResponse';\n\n/**\n * Convert addresses into geographic coordinates (geocoding).\n *\n * The Geocode service translates addresses and place names into geographic coordinates,\n * enabling you to position markers on maps, calculate routes, or perform spatial analysis.\n *\n * @remarks\n * This service is optimized for address lookup and does not return POIs (Points of Interest).\n * For POI search, use the {@link search} function instead.\n *\n * Features:\n * - Highly tolerant of typos and incomplete addresses\n * - Handles various address formats and components\n * - Supports street addresses, intersections, and cross streets\n * - Works with higher-level geographies (cities, counties, states, countries)\n * - Returns structured address components\n *\n * @param params - Geocoding parameters including the address query\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to geocoded location results\n *\n * @example\n * ```typescript\n * // Geocode a complete address\n * const result = await geocode({\n * key: 'your-api-key',\n * query: '1600 Pennsylvania Avenue NW, Washington, DC'\n * });\n *\n * // Geocode with partial address\n * const partialResult = await geocode({\n * key: 'your-api-key',\n * query: 'Amsterdam, Netherlands'\n * });\n *\n * // Geocode with bias towards specific location\n * const biasedResult = await geocode({\n * key: 'your-api-key',\n * query: 'Main Street',\n * at: [4.9041, 52.3676], // Bias toward Amsterdam\n * limit: 5\n * });\n *\n * // Geocode an intersection\n * const intersection = await geocode({\n * key: 'your-api-key',\n * query: '5th Avenue & 42nd Street, New York'\n * });\n * ```\n *\n * @see [Geocode API Documentation](https://docs.tomtom.com/search-api/documentation/geocoding-service/geocode)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Geocoding Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/geocoding)\n *\n * @group Geocoding\n */\nexport const geocode = async (\n params: GeocodingParams,\n customTemplate?: Partial<GeocodingTemplate>,\n): Promise<GeocodingResponse> => callService(params, { ...geocodingTemplate, ...customTemplate }, 'Geocode');\n\n/**\n *\n * @param query\n * @group Geocoding\n */\nexport const geocodeOne = async (query: string): Promise<Place<GeocodingProps>> =>\n (await geocode({ query, limit: 1 })).features[0];\n","import type { CommonPlaceProps, Places, PolygonFeatures } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { GeometryDataTemplate } from './geometryDataTemplate';\nimport { geometryDataTemplate } from './geometryDataTemplate';\nimport type { GeometryDataParams, GeometryParams, GeometryPlaceParams } from './types/geometryDataParams';\n\n/**\n * Merge our internal Places \"properties\" response with Geometry data\n * @param places\n * @param geometries\n * @returns FeatureCollection<Polygon | MultiPolygon>,\n */\nconst mergePlacesWithGeometries = (places: Places, geometries: PolygonFeatures): PolygonFeatures<CommonPlaceProps> => {\n const placesIdMap = places.features.reduce(\n (acc, place) => {\n const geometryId = place.properties.dataSources?.geometry?.id;\n\n if (geometryId) {\n acc[geometryId] = {\n ...place.properties,\n placeCoordinates: place.geometry.coordinates,\n };\n }\n return acc;\n },\n {} as Record<string, unknown>,\n );\n\n const features = geometries.features.map((feature) => {\n if (feature.id && placesIdMap[feature.id]) {\n return { ...feature, properties: placesIdMap[feature.id] };\n }\n\n return feature;\n });\n\n return {\n type: 'FeatureCollection',\n bbox: geometries.bbox,\n features,\n } as PolygonFeatures<CommonPlaceProps>;\n};\n\n/**\n * Retrieve polygon geometries representing geographic area boundaries.\n *\n * The Geometry Data service returns coordinate sets that define the outlines of\n * geographic areas such as cities, countries, administrative regions, or POI footprints.\n * These polygons enable visualization of area boundaries, spatial analysis, and\n * geofencing applications.\n *\n * @remarks\n * Key features:\n * - **Batch requests**: Fetch up to 20 geometries in a single call\n * - **Multiple scales**: From countries down to building footprints\n * - **Place integration**: Can merge with place data for enriched results\n * - **Standard GeoJSON**: Returns standard Polygon/MultiPolygon features\n *\n * Common use cases:\n * - Display city or country boundaries on maps\n * - Show POI building footprints\n * - Create geofences for spatial queries\n * - Visualize administrative divisions\n * - Calculate areas and spatial relationships\n *\n * @param params - Geometry parameters with IDs or places to fetch boundaries for\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to polygon features representing area boundaries\n *\n * @example\n * ```typescript\n * // Fetch geometry by ID\n * const cityBoundary = await geometryData({\n * key: 'your-api-key',\n * geometries: ['geometry-id-123']\n * });\n *\n * // Fetch multiple geometries at once\n * const boundaries = await geometryData({\n * key: 'your-api-key',\n * geometries: ['country-id-1', 'city-id-2', 'poi-id-3']\n * });\n *\n * // Fetch and merge with place data\n * const searchResults = await search({ query: 'Amsterdam' });\n * const withBoundaries = await geometryData({\n * key: 'your-api-key',\n * geometries: searchResults // Places with geometry IDs\n * });\n * // Result includes both place properties and polygon boundaries\n * ```\n *\n * @see [Geometry Data API Documentation](https://docs.tomtom.com/search-api/documentation/additional-data-service/additional-data)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Geometry Data Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/geometry-data)\n *\n * @group Geometry\n */\nexport async function geometryData(\n params: GeometryDataParams,\n customTemplate?: Partial<GeometryDataTemplate>,\n): Promise<PolygonFeatures>;\nexport async function geometryData(\n params: GeometryPlaceParams,\n customTemplate?: Partial<GeometryDataTemplate>,\n): Promise<PolygonFeatures<CommonPlaceProps>>;\nexport async function geometryData(params: GeometryParams, customTemplate?: Partial<GeometryDataTemplate>) {\n const geometryResult = await callService(params, { ...geometryDataTemplate, ...customTemplate }, 'GeometryData');\n\n // If params.geometries is a FeatureCollection(Place), the properties will be merged with geometry results.\n if (!Array.isArray(params.geometries) && params.geometries.type === 'FeatureCollection') {\n return mergePlacesWithGeometries(params.geometries, geometryResult);\n }\n\n return geometryResult;\n}\n","import { callService } from '../shared/serviceTemplate';\nimport type { PlaceByIdTemplate } from './placeByIdTemplate';\nimport { placeByIdTemplate } from './placeByIdTemplate';\nimport type { PlaceByIdParams, PlaceByIdResponse } from './types';\n\n/**\n * Retrieve detailed information about a place using its unique identifier.\n *\n * The Place by ID service fetches comprehensive data for a specific place when you\n * have its ID from a previous search or from a place's dataSources. This is useful\n * for getting additional details or refreshing information about a known location.\n *\n * @remarks\n * Use cases:\n * - **Fetch POI details**: Get extended information like reviews, photos, amenities\n * - **Refresh place data**: Update information for a cached place\n * - **Deep linking**: Allow users to share/bookmark specific places\n * - **Related POI navigation**: Explore parent/child relationships\n *\n * The ID can be obtained from:\n * - Previous search results (place.id)\n * - POI details data source (place.properties.dataSources.poiDetails.id)\n * - Related POIs (place.properties.relatedPois[].id)\n * - Deep links or bookmarks\n *\n * @param params - Place by ID parameters with the place identifier\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to detailed place information\n *\n * @example\n * ```typescript\n * // Get place by ID from search result\n * const searchResult = await search({ query: 'Eiffel Tower' });\n * const placeId = searchResult.features[0].id;\n *\n * const placeDetails = await placeById({\n * key: 'your-api-key',\n * entityId: placeId\n * });\n *\n * // Get extended POI details\n * const place = searchResult.features[0];\n * const poiDetailsId = place.properties.dataSources?.poiDetails?.id;\n *\n * if (poiDetailsId) {\n * const detailedPOI = await placeById({\n * key: 'your-api-key',\n * entityId: poiDetailsId\n * });\n * // May include additional photos, reviews, extended hours, etc.\n * }\n *\n * // Navigate to related POI\n * const relatedPOI = place.properties.relatedPois?.[0];\n * if (relatedPOI) {\n * const parentPlace = await placeById({\n * key: 'your-api-key',\n * entityId: relatedPOI.id\n * });\n * console.log('Parent location:', parentPlace.properties.address);\n * }\n * ```\n *\n * @see [Place by ID API Documentation](https://docs.tomtom.com/search-api/documentation/place-by-id-service/place-by-id)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n *\n * @group Place\n */\nexport const placeById = async (\n params: PlaceByIdParams,\n customTemplate?: Partial<PlaceByIdTemplate>,\n): Promise<PlaceByIdResponse> => callService(params, { ...placeByIdTemplate, ...customTemplate }, 'PlaceById');\n\nexport default placeById;\n","import { bboxFromGeoJSON, PolygonFeature, PolygonFeatures } from '@tomtom-org/maps-sdk/core';\nimport { SDKServiceError } from '../shared/errors';\nimport { callService } from '../shared/serviceTemplate';\nimport type { ReachableRangeTemplate } from './reachableRangeTemplate';\nimport { reachableRangeTemplate } from './reachableRangeTemplate';\nimport type { ReachableRangeParams } from './types/reachableRangeParams';\n\n/**\n * Calculate the area reachable from a starting point within given constraints.\n *\n * The Reachable Range service (also known as isochrone) computes a polygon representing\n * all locations that can be reached from an origin within specified limits of time, distance,\n * or energy consumption. This is essential for range analysis, service area visualization,\n * and logistics planning.\n *\n * @remarks\n * Key features:\n * - **Time-based ranges**: Areas reachable within a time budget (e.g., 30 minutes)\n * - **Distance-based ranges**: Areas within a distance limit (e.g., 50km)\n * - **Energy-based ranges**: EV range considering battery consumption\n * - **Traffic awareness**: Accounts for current and historic traffic patterns\n * - **Vehicle-specific**: Considers vehicle characteristics and constraints\n *\n * Common use cases:\n * - **Service area mapping**: \"Show areas we can deliver to within 1 hour\"\n * - **EV range visualization**: Display drivable range on current battery\n * - **Real estate**: \"Find homes within 45 minutes of workplace\"\n * - **Emergency services**: Calculate ambulance/fire truck response areas\n * - **Market analysis**: Identify customer catchment areas\n * - **Location planning**: Optimize facility placement based on coverage\n *\n * @param params Reachable range parameters including origin and budget constraints\n * @param customTemplate Advanced customization for request/response handling\n *\n * @returns Promise resolving to a polygon representing the reachable area\n *\n * @example\n * ```typescript\n * // Calculate 30-minute drive time range\n * const range30min = await calculateReachableRange({\n * key: 'your-api-key',\n * origin: [4.9041, 52.3676], // Amsterdam\n * timeBudgetInSec: 1800 // 30 minutes\n * });\n *\n * // Calculate 50km distance range\n * const range50km = await calculateReachableRange({\n * key: 'your-api-key',\n * origin: [4.9041, 52.3676],\n * distanceBudgetInMeters: 50000\n * });\n *\n * // EV range based on battery\n * const evRange = await calculateReachableRange({\n * key: 'your-api-key',\n * origin: [4.9041, 52.3676],\n * fuelBudgetInkWh: 20, // Remaining battery\n * vehicleEngineType: 'electric',\n * constantSpeedConsumptionInkWhPerHundredkm: [[50, 8], [80, 12]]\n * });\n *\n * // Traffic-aware range at departure time\n * const morningRange = await calculateReachableRange({\n * key: 'your-api-key',\n * origin: [4.9041, 52.3676],\n * timeBudgetInSec: 2700, // 45 minutes\n * departAt: new Date('2025-10-20T08:00:00Z') // Rush hour\n * });\n * ```\n *\n * @see [Reachable Range API Documentation](https://docs.tomtom.com/routing-api/documentation/routing/calculate-reachable-range)\n * @see [Routing Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/routing/quickstart)\n *\n * @group Routing\n */\nexport const calculateReachableRange = async (\n params: ReachableRangeParams,\n customTemplate?: Partial<ReachableRangeTemplate>,\n): Promise<PolygonFeature<ReachableRangeParams>> =>\n callService(params, { ...reachableRangeTemplate, ...customTemplate }, 'Reachable Range');\n\n/**\n * Calculate multiple reachable range areas from different origins or with different constraints.\n *\n * Computes several isochrone polygons in sequence, useful for comparing ranges from multiple\n * locations, visualizing multiple time/distance rings from the same origin, or analyzing\n * different vehicle scenarios.\n *\n * @remarks\n * Use cases:\n * - **Multi-location comparison**: Compare service areas of different store locations\n * - **Concentric ranges**: Create 15/30/45 minute drive time rings from one origin\n * - **Scenario analysis**: Compare ranges for different vehicle types or times of day\n * - **Coverage optimization**: Find optimal facility locations with minimal overlap\n *\n * Note: Ranges are calculated sequentially to avoid rate limiting. For large batches,\n * consider implementing your own parallel processing with appropriate throttling.\n *\n * @param paramsArray Array of reachable range parameters, one for each area to calculate\n * @param options.signal An `AbortSignal` to cancel in-flight requests between iterations.\n * @param customTemplate Advanced customization for request/response handling\n *\n * @returns Promise resolving to a FeatureCollection of reachable area polygons\n *\n * @example\n * ```typescript\n * // Calculate concentric drive time rings (15, 30, 45 minutes)\n * const timeRings = await calculateReachableRanges([\n * { key: 'your-api-key', origin: [4.9, 52.3], timeBudgetInSec: 900 },\n * { key: 'your-api-key', origin: [4.9, 52.3], timeBudgetInSec: 1800 },\n * { key: 'your-api-key', origin: [4.9, 52.3], timeBudgetInSec: 2700 }\n * ]);\n *\n * // Compare service areas of multiple stores\n * const storeRanges = await calculateReachableRanges([\n * { key: 'your-api-key', origin: [4.9, 52.3], timeBudgetInSec: 1800 },\n * { key: 'your-api-key', origin: [4.5, 51.9], timeBudgetInSec: 1800 },\n * { key: 'your-api-key', origin: [5.1, 52.1], timeBudgetInSec: 1800 }\n * ]);\n *\n * // Compare EV ranges at different battery levels\n * const batteryRanges = await calculateReachableRanges([\n * {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * fuelBudgetInkWh: 10,\n * vehicleEngineType: 'electric'\n * },\n * {\n * key: 'your-api-key',\n * origin: [4.9, 52.3],\n * fuelBudgetInkWh: 20,\n * vehicleEngineType: 'electric'\n * }\n * ]);\n * ```\n *\n * @see [Reachable Range API Documentation](https://docs.tomtom.com/routing-api/documentation/routing/calculate-reachable-range)\n * @see [Routing Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/routing/quickstart)\n *\n * @group Routing\n */\nexport const calculateReachableRanges = async (\n paramsArray: ReachableRangeParams[],\n options?: { signal?: AbortSignal },\n customTemplate?: Partial<ReachableRangeTemplate>,\n): Promise<PolygonFeatures<ReachableRangeParams>> => {\n const features: PolygonFeature<ReachableRangeParams>[] = [];\n for (const params of paramsArray) {\n // Throws AbortError if a newer call has cancelled this one before the next request starts\n options?.signal?.throwIfAborted();\n try {\n // we sequentially fetch reachable ranges (less speed but better to prevent QPS limit breaches):\n features.push(await calculateReachableRange(params, customTemplate));\n } catch (error) {\n // Re-throw non-API errors (e.g. validation/programming errors) and critical HTTP errors\n // (403 Forbidden, 429 Too Many Requests) — only silently skip API errors that indicate\n // no reachable range could be computed at this location (e.g. no road network).\n if (!(error instanceof SDKServiceError) || error.status === 403 || error.status === 429) {\n throw error;\n }\n }\n }\n const bbox = bboxFromGeoJSON(features);\n return { type: 'FeatureCollection', ...(bbox && { bbox }), features };\n};\n","import type { Place, RevGeoAddressProps } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { ReverseGeocodingTemplate } from './reverseGeocodingTemplate';\nimport { reverseGeocodingTemplate } from './reverseGeocodingTemplate';\nimport type { ReverseGeocodingParams } from './types/reverseGeocodingParams';\n\n/**\n * Response from the reverse geocoding service.\n *\n * Contains a place with address information for the given coordinates.\n *\n * @group Reverse Geocoding\n */\nexport type ReverseGeocodingResponse = Place<RevGeoAddressProps>;\n\n/**\n * Convert geographic coordinates into human-readable addresses (reverse geocoding).\n *\n * Reverse geocoding translates latitude/longitude coordinates into street addresses,\n * which is essential for location-based applications that need to display addresses\n * from GPS coordinates or map clicks.\n *\n * @remarks\n * Common use cases:\n * - **Tracking applications**: Convert GPS coordinates from devices into addresses\n * - **Map interactions**: Display address when user clicks on map\n * - **Location sharing**: Show readable location instead of coordinates\n * - **Delivery apps**: Confirm pickup/dropoff addresses from driver location\n * - **Asset tracking**: Display current location of vehicles or equipment\n *\n * Features:\n * - Returns complete address hierarchy (street, city, state, country)\n * - Supports cross-street results\n * - Includes side of street information\n * - Provides address ranges for streets\n * - Returns multiple result types (street, POI, geography)\n *\n * @param params - Reverse geocoding parameters including coordinates\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to the address for the given coordinates\n *\n * @example\n * ```typescript\n * // Get address for coordinates\n * const address = await reverseGeocode({\n * key: 'your-api-key',\n * position: [4.9041, 52.3676] // Amsterdam coordinates\n * });\n * // Returns: Dam, 1012 Amsterdam, Netherlands\n *\n * // Get address with specific street number\n * const specificAddress = await reverseGeocode({\n * key: 'your-api-key',\n * position: [-77.0369, 38.8977], // Washington DC\n * number: '1600'\n * });\n * // Returns: 1600 Pennsylvania Avenue NW\n *\n * // Get nearest cross street\n * const crossStreet = await reverseGeocode({\n * key: 'your-api-key',\n * position: [-74.0060, 40.7128], // New York\n * returnRoadUse: true\n * });\n * ```\n *\n * @see [Reverse Geocode API Documentation](https://docs.tomtom.com/search-api/documentation/reverse-geocoding-service/reverse-geocode)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Reverse Geocoding Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/reverse-geocoding)\n *\n * @group Reverse Geocoding\n */\nexport const reverseGeocode = async (\n params: ReverseGeocodingParams,\n customTemplate?: Partial<ReverseGeocodingTemplate>,\n): Promise<ReverseGeocodingResponse> =>\n callService(params, { ...reverseGeocodingTemplate, ...customTemplate }, 'ReverseGeocode');\n\nexport default reverseGeocode;\n","import type { Routes } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { CalculateRouteTemplate } from './calculateRouteTemplate';\nimport { calculateRouteTemplate } from './calculateRouteTemplate';\nimport type { CalculateRouteParams } from './types/calculateRouteParams';\n\n/**\n * Calculates a route between an origin and destination, optionally passing through extra waypoints.\n *\n * @param params - Route calculation parameters including locations, travel mode, and other options\n * @param customTemplate - Optional template customization for request/response handling\n * @returns Promise resolving to calculated route(s) with geometry, distance, and travel time\n *\n * @see [Calculate Route API Documentation](https://docs.tomtom.com/routing-api/documentation/tomtom-maps/calculate-route)\n *\n * @group Routing\n */\nexport const calculateRoute = async (\n params: CalculateRouteParams,\n customTemplate?: Partial<CalculateRouteTemplate>,\n): Promise<Routes> => callService(params, { ...calculateRouteTemplate, ...customTemplate }, 'Routing');\n","import { z } from 'zod';\nimport { commonSearchParamsSchema } from '../search/commonSearchParamsSchema';\nimport { commonGeocodeAndFuzzySearchParamsSchema } from '../shared/schema/commonGeocodeAndFuzzySearchParamsSchema';\n\nconst fuzzySearchRequestOptional = z.object({\n minFuzzyLevel: z\n .number()\n .min(1)\n .max(4)\n .optional()\n .describe('Minimum fuzzy matching level (1-4, higher allows more typos)'),\n maxFuzzyLevel: z\n .number()\n .min(1)\n .max(4)\n .optional()\n .describe('Maximum fuzzy matching level (1-4, higher allows more typos)'),\n});\n\n/**\n * @ignore\n */\nexport const fuzzySearchRequestSchema = commonSearchParamsSchema.extend(\n commonGeocodeAndFuzzySearchParamsSchema.extend(fuzzySearchRequestOptional.shape).shape,\n);\n","import { bboxFromGeoJSON, bboxOnlyIfWithArea } from '@tomtom-org/maps-sdk/core';\nimport { latLonAPIToPosition } from '../shared/geometry';\nimport { parseSearchAPIResult, parseSummaryAPI } from '../shared/searchResultParsing';\nimport type { FuzzySearchResponse, FuzzySearchResponseAPI, QueryIntent, QueryIntentAPI } from './types';\n\nconst queryIntentApiToSdk = (intentApi: QueryIntentAPI): QueryIntent => {\n let intent;\n switch (intentApi.type) {\n case 'COORDINATE':\n intent = { ...intentApi, details: { position: latLonAPIToPosition(intentApi.details) } };\n break;\n case 'NEARBY':\n intent = {\n ...intentApi,\n details: {\n position: latLonAPIToPosition({ lon: intentApi.details.lon, lat: intentApi.details.lat }),\n text: intentApi.details.text,\n query: intentApi.details.query,\n },\n };\n break;\n case 'BOOKMARK':\n case 'W3W':\n intent = intentApi;\n }\n return intent;\n};\n\n/**\n * Default function to parse a fuzzy search response.\n * @param apiResponse The API response.\n */\nexport const parseFuzzySearchResponse = (apiResponse: FuzzySearchResponseAPI): FuzzySearchResponse => {\n const features = apiResponse.results.map(parseSearchAPIResult);\n const bbox = bboxOnlyIfWithArea(bboxFromGeoJSON(features));\n return {\n type: 'FeatureCollection',\n properties: {\n ...parseSummaryAPI(apiResponse.summary),\n queryIntent: apiResponse.summary.queryIntent.map(queryIntentApiToSdk),\n },\n features,\n ...(bbox && { bbox }),\n };\n};\n","import type { ServiceTemplate } from '../shared';\nimport { get } from '../shared/fetch';\nimport { fuzzySearchRequestSchema } from './fuzzySearchRequestSchema';\nimport { buildFuzzySearchRequest } from './requestBuilder';\nimport { parseFuzzySearchResponse } from './responseParser';\nimport type { FuzzySearchParams, FuzzySearchResponse, FuzzySearchResponseAPI } from './types';\n\n/**\n * Fuzzy search service template type.\n * @ignore\n */\nexport type FuzzySearchTemplate = ServiceTemplate<FuzzySearchParams, URL, FuzzySearchResponseAPI, FuzzySearchResponse>;\n\n/**\n * Fuzzy search service template main implementation.\n * @ignore\n */\nexport const fuzzySearchTemplate: FuzzySearchTemplate = {\n requestValidation: { schema: fuzzySearchRequestSchema },\n buildRequest: buildFuzzySearchRequest,\n sendRequest: get,\n parseResponse: parseFuzzySearchResponse,\n};\n","import { bboxFromGeoJSON } from '@tomtom-org/maps-sdk/core';\nimport { arrayToCSV } from '../shared/arrays';\nimport { appendCommonSearchParams, PLACES_URL_PATH } from '../shared/request/commonSearchRequestBuilder';\nimport { appendByJoiningParamValue, appendOptionalParam } from '../shared/request/requestBuildingUtils';\nimport type { FuzzySearchParams } from './types';\n\nconst buildUrlBasePath = (mergedOptions: FuzzySearchParams): string =>\n mergedOptions.customServiceBaseURL ??\n `${mergedOptions.commonBaseURL}${PLACES_URL_PATH}/search/${mergedOptions.query}.json`;\n\n/**\n * Default function for building a fuzzy search request from {@link FuzzySearchParams}\n * @param params The fuzzy search parameters, with global configuration already merged into them.\n */\nexport const buildFuzzySearchRequest = (params: FuzzySearchParams): URL => {\n const url = new URL(`${buildUrlBasePath(params)}`);\n appendCommonSearchParams(url, params);\n const urlParams = url.searchParams;\n appendOptionalParam(urlParams, 'typeahead', params.typeahead);\n appendOptionalParam(urlParams, 'ofs', params.offset);\n appendByJoiningParamValue(urlParams, 'countrySet', params.countries);\n appendOptionalParam(urlParams, 'radius', params.radiusMeters);\n const bbox = params.boundingBox && bboxFromGeoJSON(params.boundingBox);\n if (bbox) {\n urlParams.append('topLeft', arrayToCSV([bbox[3], bbox[0]]));\n urlParams.append('btmRight', arrayToCSV([bbox[1], bbox[2]]));\n }\n appendOptionalParam(urlParams, 'minFuzzyLevel', params.minFuzzyLevel);\n appendOptionalParam(urlParams, 'maxFuzzyLevel', params.maxFuzzyLevel);\n return url;\n};\n","import type { Place, Places, SearchPlaceProps } from '@tomtom-org/maps-sdk/core';\nimport type { FuzzySearchParams, QueryIntent } from '../fuzzy-search';\nimport { fuzzySearch } from '../fuzzy-search/fuzzySearch';\nimport type { FuzzySearchTemplate } from '../fuzzy-search/fuzzySearchTemplate';\nimport type { GeometrySearchParams } from '../geometry-search';\nimport { geometrySearch } from '../geometry-search/geometrySearch';\nimport type { GeometrySearchTemplate } from '../geometry-search/geometrySearchTemplate';\nimport type { SearchSummary } from '../shared';\n\ntype SearchFeatureCollectionProps = SearchSummary & {\n queryIntent?: QueryIntent[];\n};\n\n/**\n * Search service response containing places that match the query.\n *\n * Collection of place features with search-specific properties like relevance scores and distances.\n *\n * @group Search\n */\nexport type SearchResponse = Places<SearchPlaceProps, SearchFeatureCollectionProps>;\n\n/**\n * Universal search function for finding places by text query or within geometries.\n *\n * This is a unified interface that automatically routes to either:\n * - **Geometry Search**: When geometries parameter is provided (search within specific areas)\n * - **Fuzzy Search**: When no geometries provided (free-text search)\n *\n * @remarks\n * The search service provides:\n * - POI (Points of Interest) search\n * - Address search\n * - Geographic area search\n * - Category-based filtering\n * - Position-based relevance ranking\n *\n * Results are ranked by relevance with scores and optional distances.\n *\n * @param params - Search parameters (either GeometrySearchParams or FuzzySearchParams)\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to a collection of matching places\n *\n * @example\n * ```typescript\n * // Free-text search near a location\n * const results = await search({\n * key: 'your-api-key',\n * query: 'pizza restaurant',\n * at: [4.9041, 52.3676], // Amsterdam\n * limit: 10\n * });\n *\n * // Search within a specific area\n * const areaResults = await search({\n * key: 'your-api-key',\n * query: 'coffee shop',\n * geometries: [polygon], // Search within this polygon\n * limit: 20\n * });\n *\n * // Category search\n * const restaurants = await search({\n * key: 'your-api-key',\n * query: 'restaurant',\n * categorySet: [7315], // Restaurant category\n * at: [4.9041, 52.3676],\n * radius: 5000 // Within 5km\n * });\n * ```\n *\n * @see [Search API Documentation](https://docs.tomtom.com/search-api/documentation/search-service/search-service)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Search Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/search)\n *\n * @group Search\n */\nexport const search = async (\n params: GeometrySearchParams | FuzzySearchParams,\n customTemplate?: Partial<GeometrySearchTemplate | FuzzySearchTemplate>,\n): Promise<SearchResponse> =>\n 'geometries' in params\n ? geometrySearch(params, customTemplate as GeometrySearchTemplate)\n : fuzzySearch(params, customTemplate as FuzzySearchTemplate);\n\n/**\n * Search for a single place by text query.\n *\n * Convenience function that calls {@link search} and returns the first result.\n *\n * @param query - Search query string\n * @returns Promise resolving to the first matching place, or undefined if no results\n *\n * @example\n * ```typescript\n * const place = await searchOne('Vondelpark Amsterdam');\n * if (place) {\n * console.log(place.properties.name);\n * }\n * ```\n *\n * @remarks\n * * Useful to quickly find a single place, particularly a POI.\n * * If you want to find a single address, consider 'geocodeOne'.\n *\n * @group Search\n */\nexport const searchOne = async (query: string): Promise<Place<SearchPlaceProps> | undefined> =>\n (await search({ query, limit: 1 })).features[0];\n","import { callService } from '../shared/serviceTemplate';\nimport type { FuzzySearchTemplate } from './fuzzySearchTemplate';\nimport { fuzzySearchTemplate } from './fuzzySearchTemplate';\nimport type { FuzzySearchParams, FuzzySearchResponse } from './types';\n\n/**\n * Search for places using free-text queries with fuzzy matching.\n *\n * The Fuzzy Search service provides a flexible search that handles typos, abbreviations,\n * and incomplete addresses. It searches across POIs (Points of Interest), addresses,\n * and geographic areas to find the best matches for your query.\n *\n * @remarks\n * Key features:\n * - **Typo tolerance**: Handles misspellings and typing errors\n * - **Partial matching**: Works with incomplete queries\n * - **Multi-category search**: Searches POIs, addresses, and places simultaneously\n * - **Position bias**: Prioritizes results near a given location\n * - **Flexible input**: Accepts natural language queries\n *\n * The service is ideal for:\n * - User-facing search boxes where typos are common\n * - Location lookup without knowing exact names\n * - General \"find anything\" search functionality\n * - Autocomplete with final selection\n *\n * @param params Fuzzy search parameters including the search query\n * @param customTemplate Advanced customization for request/response handling\n *\n * @returns Promise resolving to a collection of matching places\n *\n * @example\n * ```typescript\n * // Basic search with typo tolerance\n * const results = await fuzzySearch({\n * key: 'your-api-key',\n * query: 'amstrdam' // Typo: missing 'e'\n * });\n * // Still finds \"Amsterdam\"\n *\n * // Search near a specific location\n * const nearby = await fuzzySearch({\n * key: 'your-api-key',\n * query: 'pizza',\n * at: [4.9041, 52.3676], // Amsterdam\n * radius: 2000, // Within 2km\n * limit: 10\n * });\n *\n * // Search with category filter\n * const restaurants = await fuzzySearch({\n * key: 'your-api-key',\n * query: 'italian',\n * categorySet: [7315], // Restaurant category\n * at: [4.9041, 52.3676]\n * });\n *\n * // Partial address search\n * const addresses = await fuzzySearch({\n * key: 'your-api-key',\n * query: '123 main st',\n * countrySet: ['US'],\n * limit: 5\n * });\n * ```\n *\n * @see [Fuzzy Search API Documentation](https://docs.tomtom.com/search-api/documentation/search-service/fuzzy-search)\n * @see [Places Quickstart Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/quickstart)\n * @see [Search Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/places/search)\n *\n * @ignore (exposed via 'search')\n */\nexport const fuzzySearch = async (\n params: FuzzySearchParams,\n customTemplate?: Partial<FuzzySearchTemplate>,\n): Promise<FuzzySearchResponse> => callService(params, { ...fuzzySearchTemplate, ...customTemplate }, 'FuzzySearch');\n\nexport default fuzzySearch;\n","import type { TrafficIncidentDetails } from '@tomtom-org/maps-sdk/core';\nimport { callService } from '../shared/serviceTemplate';\nimport type { TrafficIncidentDetailsTemplate } from './trafficIncidentDetailsTemplate';\nimport { trafficIncidentDetailsTemplate } from './trafficIncidentDetailsTemplate';\nimport type { TrafficIncidentDetailsParams } from './types/trafficIncidentDetailsParams';\n\n/**\n * Fetch detailed information about traffic incidents.\n *\n * Query incidents either by a geographic bounding box or by a list of incident IDs.\n * Results are GeoJSON Features whose geometry is a `Point` (localised incidents) or\n * a `LineString` (incidents spanning a stretch of road).\n *\n * @remarks\n * **Two query modes:**\n *\n * - **Bounding box** (`bbox`): Returns all incidents within the given area.\n * Maximum area is 10,000 km².\n * - **By IDs** (`ids`): Returns the specified incidents directly.\n * GET is used automatically for up to 5 IDs; POST for up to 100 IDs.\n *\n * **Key data provided per incident:**\n * - Category (`iconCategory`): type of incident (accident, roadworks, jam, etc.)\n * - Delay magnitude: severity of the delay (`minor`, `moderate`, `major`, …)\n * - Geometry: exact location or extent of the incident on the road network\n * - Time information: start/end times and whether the incident is `present` or `future`\n * - Events: one or more detailed event descriptions\n *\n * @param params - Traffic Incident Details parameters (bbox or ids)\n * @param customTemplate - Advanced customization for request/response handling\n *\n * @returns Promise resolving to a {@link TrafficIncidentDetails} object containing the matching incidents\n *\n * @example\n * ```typescript\n * // Query by bounding box (Amsterdam area)\n * const result = await trafficIncidentDetails({\n * bbox: [4.728, 52.278, 5.080, 52.479]\n * });\n *\n * result.incidents.forEach(incident => {\n * console.log(incident.properties.iconCategory); // 'accident' | 'jam' | …\n * console.log(incident.properties.magnitudeOfDelay); // 'minor' | 'major' | …\n * console.log(incident.geometry); // Point or LineString\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Query up to 5 specific incidents by ID (GET)\n * const result = await trafficIncidentDetails({\n * ids: ['incident-id-1', 'incident-id-2']\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Query many incident IDs — POST is used automatically when ids.length > 5\n * const result = await trafficIncidentDetails({\n * ids: largeIdArray\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Filter by category and include future incidents\n * const result = await trafficIncidentDetails({\n * bbox: [4.728, 52.278, 5.080, 52.479],\n * categoryFilter: ['accident', 'road-closed'],\n * timeValidityFilter: ['present', 'future']\n * });\n * ```\n *\n * @see [Incident Details API Documentation](https://docs.tomtom.com/traffic-api/documentation/tomtom-orbis-maps/traffic-incidents/incident-details)\n * @see [Incident Details Guide](https://docs.tomtom.com/maps-sdk-js/guides/services/traffic/incident-details)\n *\n * @group Traffic\n */\nexport const trafficIncidentDetails = async (\n params: TrafficIncidentDetailsParams,\n customTemplate?: Partial<TrafficIncidentDetailsTemplate>,\n): Promise<TrafficIncidentDetails> =>\n callService(params, { ...trafficIncidentDetailsTemplate, ...customTemplate }, 'TrafficIncidentDetails');\n"],"names":["APICode","SDKError","Error","constructor","message","service","issues","super","this","captureStackTrace","APIErrorCode","TOO_MANY_REQUESTS","FORBIDDEN","SDKServiceError","status","parseDefaultResponseError","error","serviceName","data","errorText","buildResponseError","parseResponseError","fetchError","buildValidationError","commonServiceRequestSchema","z","object","apiKey","string","optional","describe","commonBaseURL","customServiceBaseURL","language","ValidationError","zodError","map","issue","path","length","join","callService","async","params","template","customApiVersion","getAPIVersion","mergedParams","mergeFromGlobal","apiVersion","validateRequest","config","validation","schema","extend","shape","superRefine","ctx","addIssue","code","refinements","refinement","check","safeParse","success","validateRequestSchema","requestValidation","e","Promise","reject","apiRequest","buildRequest","headers","generateTomTomHeaders","onAPIRequest","apiResponse","sendRequest","onAPIResponse","parseResponse","FetchError","name","returnOrThrow","response","ok","json","errorBody","contentType","get","bodyUsed","statusText","includes","detailedError","text","url","fetch","post","input","method","body","JSON","stringify","fetchWith","lineStringCoordsSchema","array","number","geometrySchema","type","enum","coordinates","union","radius","radiusMeters","bbox","refine","Boolean","featureSchema","literal","geometry","id","properties","any","featureCollectionSchema","features","hasLngLatSchema","tuple","min","max","geoJsonbBoxSchema","arr","GeoJSONSchema","hasBBoxSchema","autocompleteSearchRequestMandatory","query","autocompleteSearchRequestOptional","position","limit","countries","resultType","autocompleteSearchRequestSchema","appendCommonParams","urlParams","append","String","appendByRepeatingParamName","paramName","paramArray","param","appendByJoiningParamValue","values","Array","isArray","appendOptionalParam","value","isNil","appendLatLonParamsFromPosition","hasLngLat","getPosition","PLACES_URL_PATH","appendCommonSearchParams","searchUrl","searchParams","fuelTypes","indexes","poiBrands","poiCategories","poiCategory","poiCategoriesToID","connectors","mapcodes","extendedPostalCodesFor","minPowerKW","maxPowerKW","view","openingHours","timeZone","relatedPois","geographyTypes","buildAutocompleteSearchRequest","URL","mergedOptions","csvLatLngToPosition","csv","splitLatLng","split","Number","positionToCSVLatLon","apiToGeoJSONBBox","apiBBox","westSouth","eastNorth","topLeftPoint","lon","btmRightPoint","lat","southWest","northEast","latLonAPIToPosition","point","parseAutocompleteSearchResponse","geoBias","context","autocompleteSearchTemplate","autocompleteSearch","customTemplate","customize","evChargingStationsAvailabilityRequestSchema","routeTypes","buildEVChargingStationsAvailabilityRequest","buildUrlBasePath","toChargingSpeed","powerInKW","toChargingPointAvailability","chargingStations","availability","count","statusCounts","station","chargingPoint","chargingPoints","areEqual","connectorA","connectorB","ratedPowerKW","addConnectorCountAndStatus","availabilities","connector","existingAvailability","find","connectorAvailability","push","toConnectorCounts","counts","existingCount","connectorCount","addConnectorCount","toConnectorBasedAvailabilities","parseMoment","momentApi","year","month","day","dateYyyymmdd","splitDate","parseInt","parseYyyymmddDate","date","dateYYYYMMDD","hour","minute","Date","alwaysOpenInThisPeriod","timeRanges","start","end","parseOpeningHours","openingHoursApi","timeRangeApi","startTime","endTime","mode","alwaysOpenThisPeriod","parseSearchAPIResult","result","entryPoints","poi","dist","boundingBox","chargingPark","rest","omit","connectorType","chargingSpeed","toPointGeometry","distance","entrypoint","brands","brand","categoryIds","categorySet","category","parseSummaryAPI","summary","parseEVChargingStationsAvailabilityResponse","results","accessType","stations","chargingPointAvailability","connectorAvailabilities","evChargingStationsAvailabilityTemplate","apiError","errorMessage","commonGeocodeAndFuzzySearchParamsSchema","typeahead","boolean","offset","placesParamsMandatory","placesParamsOptional","views","commonPlacesParamsSchema","geocodingRequestSchema","arrayToCSV","sampleWithinMaxLength","maxLength","sampledArray","i","increment","Math","ceil","buildGeocodingRequest","bboxFromGeoJSON","parseApiResult","addressRanges","entityType","geographyType","from","to","parseGeocodingResponse","bboxOnlyIfWithArea","geocodingTemplate","geometryDataRequestMandatory","geometries","geometryDataRequestOptional","zoom","geometryDataRequestSchema","getGeometryIDs","placesArray","place","dataSources","filter","buildGeometryDataRequest","geometryIDs","appendGeometries","parseGeometryDataResponse","additionalData","flatMap","geometryData","feature","generateId","geometryDataTemplate","poiCategoriesToIdZodObject","searchExtraParamsOptional","keyof","minFuzzyLevel","mixFuzzyLevel","commonSearchParamsSchema","geometrySearchRequestMandatory","geometrySearchRequestSchema","sdkGeometryToApiGeometries","searchGeometry","vertices","coord","polygonSizeMap","Map","forEach","polygon","bboxOfPolygon","bboxFromCoordsArray","polygonSize","abs","set","entries","sort","a","b","splice","keys","findFiftyLargestPolygons","polygonCoords","buildGeometrySearchRequest","geometryList","parseGeometrySearchResponse","geometrySearchTemplate","geometrySearch","placeByIdRequestMandatory","entityId","placeByIdRequestOptional","placeByIdRequestSchema","buildPlaceByIdRequest","parsePlaceByIdResponse","placeByIdTemplate","parseRoutingResponseError","description","positiveNumber","positive","nonNegativeNumber","percentageNumber","optionalPositiveNumber","optionalNonNegativeNumber","optionalNormalizedNumber","speedToConsumptionRateSchema","speedKMH","consumptionUnitsPer100KM","baseConsumptionModelSchema","efficiency","acceleration","deceleration","uphill","downhill","speedConsumptionArray","combustionConsumptionModelSchema","speedsToConsumptionsLiters","auxiliaryPowerInLitersPerHour","fuelEnergyDensityInMJoulesPerLiter","electricConsumptionModelSchema","speedsToConsumptionsKWH","auxiliaryPowerInkW","consumptionInKWHPerKMAltitudeGain","recuperationInKWHPerKMAltitudeLoss","chargingConnectorSchema","currentType","currentTypes","plugTypes","baseLoadInkW","maxPowerInkW","maxVoltageInV","maxCurrentInA","voltageRange","minVoltageInV","batteryCurveSchema","stateOfChargeInkWh","chargingModelSchema","maxChargeKWH","batteryCurve","chargingConnectors","chargingTimeOffsetInSec","combustionEngineModelSchema","consumption","electricEngineModelSchema","charging","vehicleDimensionsSchema","lengthMeters","widthMeters","heightMeters","weightKG","axleWeightKG","predefinedVehicleModelSchema","variantId","explicitVehicleModelSchema","dimensions","engine","vehicleModelSchema","genericVehicleStateSchema","heading","combustionVehicleStateSchema","currentFuelInLiters","electricVehicleStateByPercentageSchema","currentChargePCT","electricVehicleStateByKwhSchema","currentChargeInkWh","electricVehicleStateSchema","chargingPreferencesPCTSchema","minChargeAtDestinationPCT","minChargeAtChargingStopsPCT","chargingPreferencesKWHSchema","minChargeAtDestinationInkWh","minChargeAtChargingStopsInkWh","chargingPreferencesSchema","electricVehiclePreferencesSchema","chargingPreferences","baseVehicleParamsSchema","model","restrictions","loadTypes","maxSpeedKMH","adrCode","commercial","genericVehicleParamsSchema","engineType","undefined","state","preferences","combustionVehicleParamsSchema","electricVehicleParamsSchema","vehicleParametersSchema","discriminatedUnion","commonRoutingRequestSchema","costModel","avoid","avoidableTypes","traffic","routeType","avoidAreas","thrillingParams","hilliness","windingness","travelMode","vehicle","when","option","budgetTypes","reachableRangeRequestSchemaMandatory","origin","budget","reachableRangeRequestSchemaOptional","maxFerryLengthMeters","smoothing","reachableRangeRequestSchema","buildSpeedToConsumptionString","speedsToConsumptions","speedToConsumption","appendVehicleEngineModel","appendConsumptionEfficiency","appendElectricConsumptionModel","chargingModel","appendChargingModel","consumptionModel","appendCombustionEngine","appendVehicleModel","vehicleParams","appendVehicleDimensions","appendVehicleParams","combustionState","electricState","kwhElectricState","pctElectricState","appendVehicleState","chargingPrefs","kwhChargingPrefs","pctChargingPrefs","appendVehiclePreferences","appendVehicleRestrictions","appendCommonRoutingParams","formattedDate","toISOString","appendWhenParams","getMaxChargeKWH","appendBudget","toString","currentChargeKWH","pctState","getCurrentChargeKWH","remainingKWH","buildPostData","getPositionStrict","buildReachableRangeRequest","delete","parseReachableRangeResponse","reachableRange","boundary","longitude","latitude","reachableRangeTemplate","buildRevGeoRequest","lngLat","allowFreeformNewline","returnSpeedLimit","returnRoadUse","roadUses","parseRevGeoResponse","firstApiResult","addresses","sideOfStreet","offsetPosition","address","streetNumber","originalPosition","revGeocodeRequestMandatory","revGeocodeRequestOptional","returnMatchType","reverseGeocodingTemplate","waypointLikeSchema","pathLikeSchema","mandatorySchema","locations","optionalSchema","computeAdditionalTravelTimeFor","vehicleHeading","maxAlternatives","sectionTypes","inputSectionTypesWithGuidance","getChargingPreferences","getPositionsFromPath","pathLike","buildLocationsString","routePlanningLocationTypes","useEntryPoint","waypointInputs","waypointInput","lngLatString","getWaypointProps","buildLocationsStringFromWaypoints","types","firstPoint","firstRoutePlanningLocation","lastRoutePlanningLocation","lastPoint","positions","getFirstAndLastPoints","toLatLngPointApi","buildlocationsPostData","useEntryPoints","supportingPoints","pointWaypoints","routePlanningLocation","routePlanningLocationIndex","pathRoutePlanningLocation","supportingPointsLengthBeforePath","sections","leg","legIndex","supportingPointIndex","startPointIndex","waypointSourceType","appendPathPostData","waypoint","appendWaypointPostData","buildAvoidAreasPostData","rectangles","rect","west","south","east","north","southWestCorner","northEastCorner","buildCalculateRouteRequest","getRoutePlanningLocationType","guidance","version","phonetics","appendGuidanceParams","instructionsInclude","effectiveSectionTypes","inputSectionTypes","sectionType","appendSectionTypes","representation","extendedRouteRepresentations","postData","pathsIncluded","isLdevr","vehicleModel","chargingParameters","toCurrentType","apiCurrentType","toChargingStop","chargingInformationAtEndOfLeg","chargingConnectionInfo","chargingParkLocation","coordinate","addressParts","street","houseNumber","freeformAddress","chargingParkId","streetName","city","municipality","region","countrySubdivision","postalCode","country","plugType","chargingPlugType","currentInA","chargingCurrentInA","voltageInV","chargingVoltageInV","chargingPowerInkW","chargingCurrentType","targetChargeInPCT","targetChargeInkWh","chargingParkPowerInkW","chargingParkSpeed","parseSummary","apiSummary","lengthInMeters","historicTrafficTravelTimeInSeconds","liveTrafficIncidentsTravelTimeInSeconds","noTrafficTravelTimeInSeconds","trafficDelayInSeconds","trafficLengthInMeters","travelTimeInSeconds","departureTime","arrivalTime","deviationDistanceInMeters","deviationDistance","fuelConsumptionInLiters","deviationPoint","totalChargingTimeInSeconds","batteryConsumptionInkWh","batteryConsumptionInPCT","remainingChargeAtArrivalInkWh","remainingChargeAtArrivalInPCT","parseLegSectionProps","apiLegs","reduce","accumulatedParsedLegs","nextApiLeg","currentIndex","lastLegEndPointIndex","endPointIndex","points","toSectionProps","apiSection","toRoadStretchSectionProps","index","importantRoadStretchIndex","roadNumbers","roadNumber","toCountrySectionProps","countryCodeISO3","countryCode","toVehicleRestrictedSectionProps","toTrafficCategories","tec","causes","cause","tecMainCauseCode","calculateTrafficCategory","mainCauseCode","simpleCategory","toTrafficSectionProps","delayInSeconds","effectiveSpeedInKmh","categories","magnitudeOfDelay","indexedMagnitudes","toLaneSectionProps","lanes","laneSeparators","toSpeedLimitSectionProps","maxSpeedLimitInKmh","toRoadShieldsSectionProps","roadShieldReferences","ensureInit","getSectionMapping","mappingFunction","parseSections","apiRoute","legs","apiSections","sectionMapping","mappedSection","parseSectionsAndAppendToResult","DELTA","similar","parseGuidance","apiGuidance","instructions","lastInstructionPathIndex","apiInstruction","maneuverPoint","pathIndex","pathPointIndex","routePath","apiPoint","parseCalculateRouteResponse","routes","apiLeg","progress","parseRoute","calculateRouteTemplate","buildTrafficIncidentDetailsRequest","trafficModelId","categoryFilter","trafficIncidentToIconCategory","timeValidityFilter","appendOptionalParams","resolvedBBox","ids","parseEvent","apiEvent","iconToTrafficIncidentCategory","iconCategory","parseIncident","apiIncident","p","events","delay","timeValidity","probabilityOfOccurrence","numberOfReports","lastReportTime","tmc","apiTMC","tableNumber","tableVersion","direction","location","parseTrafficIncidentDetailsResponse","incidents","trafficIncidentDetailsTemplate","trafficIncidentCategories","customizeService","reverseGeocode","revgeoCustomize","geocode","geocodeCustomize","geometryDataCustomize","geometrySearchCustomize","calculateRoute","routingCustomize","reachableRangeCustomize","evChargingStationsAvailability","evChargingStationsAvailabilityCustomize","trafficIncidentDetails","placeByID","placeByIdCustomize","autocompleteCustomize","getPlaceWithEVAvailability","availabilityId","chargingAvailability","console","getPlacesWithEVAvailability","places","options","enhancedPlaces","placeWithAvailability","excludeIfAvailabilityUnknown","hasChargingAvailability","geocodeOne","geometryResult","placesIdMap","acc","geometryId","placeCoordinates","mergePlacesWithGeometries","placeById","calculateReachableRange","calculateReachableRanges","paramsArray","signal","throwIfAborted","fuzzySearchRequestOptional","maxFuzzyLevel","fuzzySearchRequestSchema","queryIntentApiToSdk","intentApi","intent","details","fuzzySearchTemplate","queryIntent","search","fuzzySearch","searchOne"],"mappings":"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"}