@chaosity/location-client 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -4,4 +4,9 @@ export * from '@aws/amazon-location-utilities-datatypes';
4
4
  export { GeoPlaces } from './adapters/GeoPlaces';
5
5
  export { createTransformRequest } from './maps/createTransformRequest';
6
6
  export { transformRequest } from './maps/Utils';
7
+ export { buildMapStyleUrl, fetchMapStyle } from './maps/mapStyle';
8
+ export type { MapStyleOptions } from './maps/mapStyle';
9
+ export { applyMapLanguage } from './maps/mapLanguage';
10
+ export { setPoiVisibility, setAllPoiVisibility, POI_CATEGORIES } from './maps/mapPoi';
11
+ export type { PoiCategory } from './maps/mapPoi';
7
12
  export type { ClientConfig } from './types';
package/dist/index.js CHANGED
@@ -9,4 +9,7 @@ export { GeoPlaces } from './adapters/GeoPlaces';
9
9
  // Maps utilities
10
10
  export { createTransformRequest } from './maps/createTransformRequest';
11
11
  export { transformRequest } from './maps/Utils';
12
+ export { buildMapStyleUrl, fetchMapStyle } from './maps/mapStyle';
13
+ export { applyMapLanguage } from './maps/mapLanguage';
14
+ export { setPoiVisibility, setAllPoiVisibility, POI_CATEGORIES } from './maps/mapPoi';
12
15
  // Server-only utilities are available via '@chaosity/location-client/server'
@@ -0,0 +1,19 @@
1
+ import type { Map } from 'maplibre-gl';
2
+ /**
3
+ * Apply a preferred display language to all symbol layers on a MapLibre map.
4
+ *
5
+ * AWS GeoMaps vector tiles include language-specific name properties in `name:${lang}` format
6
+ * (e.g. `name:en`, `name:fr`, `name:ja`). This function updates the `text-field` expression
7
+ * on every symbol layer to prefer the requested language, falling back to English then the
8
+ * default name if the preferred language is unavailable for a feature.
9
+ *
10
+ * Based on the approach documented at:
11
+ * https://docs.aws.amazon.com/location/latest/developerguide/how-to-set-preferred-language-map.html
12
+ *
13
+ * @param map - MapLibre Map instance
14
+ * @param language - ISO 639-1 language code (e.g. 'en', 'fr', 'de', 'ja', 'zh', 'ar')
15
+ *
16
+ * @example
17
+ * map.once('style.load', () => applyMapLanguage(map, 'fr'))
18
+ */
19
+ export declare function applyMapLanguage(map: Map, language: string): void;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Apply a preferred display language to all symbol layers on a MapLibre map.
3
+ *
4
+ * AWS GeoMaps vector tiles include language-specific name properties in `name:${lang}` format
5
+ * (e.g. `name:en`, `name:fr`, `name:ja`). This function updates the `text-field` expression
6
+ * on every symbol layer to prefer the requested language, falling back to English then the
7
+ * default name if the preferred language is unavailable for a feature.
8
+ *
9
+ * Based on the approach documented at:
10
+ * https://docs.aws.amazon.com/location/latest/developerguide/how-to-set-preferred-language-map.html
11
+ *
12
+ * @param map - MapLibre Map instance
13
+ * @param language - ISO 639-1 language code (e.g. 'en', 'fr', 'de', 'ja', 'zh', 'ar')
14
+ *
15
+ * @example
16
+ * map.once('style.load', () => applyMapLanguage(map, 'fr'))
17
+ */
18
+ export function applyMapLanguage(map, language) {
19
+ try {
20
+ const expression = language === 'en'
21
+ ? ['coalesce', ['get', 'name:en'], ['get', 'name']]
22
+ : ['coalesce', ['get', `name:${language}`], ['get', 'name:en'], ['get', 'name']];
23
+ map.getStyle().layers.forEach(layer => {
24
+ if (layer.type === 'symbol') {
25
+ const textField = map.getLayoutProperty(layer.id, 'text-field');
26
+ if (textField !== undefined && textField !== null) {
27
+ map.setLayoutProperty(layer.id, 'text-field', expression);
28
+ }
29
+ }
30
+ });
31
+ }
32
+ catch {
33
+ // Style may not be fully loaded — call after 'style.load' event
34
+ }
35
+ }
@@ -0,0 +1,44 @@
1
+ import type { Map } from 'maplibre-gl';
2
+ /**
3
+ * Mapping of POI category names to their MapLibre layer IDs in AWS GeoMaps tiles.
4
+ * Layer IDs are stable across Standard, Monochrome, and Hybrid map styles.
5
+ */
6
+ export declare const POI_CATEGORIES: {
7
+ readonly food_drink: readonly ["poi_100_food_drink"];
8
+ readonly entertainment: readonly ["poi_200_going_out_entertainment"];
9
+ readonly sights: readonly ["poi_300_sights_museums"];
10
+ readonly transit: readonly ["poi_400_transit"];
11
+ readonly accommodations: readonly ["poi_500_accommodations"];
12
+ readonly leisure: readonly ["poi_550_leisure_outdoor"];
13
+ readonly shopping: readonly ["poi_600_shopping"];
14
+ readonly business: readonly ["poi_700_business_services"];
15
+ readonly facilities: readonly ["poi_800_facilities"];
16
+ readonly areas: readonly ["poi_900_areas_buildings"];
17
+ readonly parks: readonly ["poi_landuse_park", "poi_landuse_public_complex"];
18
+ };
19
+ export type PoiCategory = keyof typeof POI_CATEGORIES;
20
+ /**
21
+ * Set the visibility of one or more POI categories on the map.
22
+ *
23
+ * @param map - MapLibre Map instance
24
+ * @param category - POI category key or array of keys
25
+ * @param visible - Whether to show (true) or hide (false) the category
26
+ *
27
+ * @example
28
+ * // Hide transit and shopping POIs
29
+ * setPoiVisibility(map, ['transit', 'shopping'], false)
30
+ *
31
+ * // Show all food & drink POIs
32
+ * setPoiVisibility(map, 'food_drink', true)
33
+ */
34
+ export declare function setPoiVisibility(map: Map, category: PoiCategory | PoiCategory[], visible: boolean): void;
35
+ /**
36
+ * Show or hide all POI layers at once.
37
+ *
38
+ * @param map - MapLibre Map instance
39
+ * @param visible - Whether to show or hide all POIs
40
+ *
41
+ * @example
42
+ * setAllPoiVisibility(map, false) // hide everything
43
+ */
44
+ export declare function setAllPoiVisibility(map: Map, visible: boolean): void;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Mapping of POI category names to their MapLibre layer IDs in AWS GeoMaps tiles.
3
+ * Layer IDs are stable across Standard, Monochrome, and Hybrid map styles.
4
+ */
5
+ export const POI_CATEGORIES = {
6
+ food_drink: ['poi_100_food_drink'],
7
+ entertainment: ['poi_200_going_out_entertainment'],
8
+ sights: ['poi_300_sights_museums'],
9
+ transit: ['poi_400_transit'],
10
+ accommodations: ['poi_500_accommodations'],
11
+ leisure: ['poi_550_leisure_outdoor'],
12
+ shopping: ['poi_600_shopping'],
13
+ business: ['poi_700_business_services'],
14
+ facilities: ['poi_800_facilities'],
15
+ areas: ['poi_900_areas_buildings'],
16
+ parks: ['poi_landuse_park', 'poi_landuse_public_complex'],
17
+ };
18
+ /**
19
+ * Set the visibility of one or more POI categories on the map.
20
+ *
21
+ * @param map - MapLibre Map instance
22
+ * @param category - POI category key or array of keys
23
+ * @param visible - Whether to show (true) or hide (false) the category
24
+ *
25
+ * @example
26
+ * // Hide transit and shopping POIs
27
+ * setPoiVisibility(map, ['transit', 'shopping'], false)
28
+ *
29
+ * // Show all food & drink POIs
30
+ * setPoiVisibility(map, 'food_drink', true)
31
+ */
32
+ export function setPoiVisibility(map, category, visible) {
33
+ const categories = Array.isArray(category) ? category : [category];
34
+ const visibility = visible ? 'visible' : 'none';
35
+ for (const cat of categories) {
36
+ for (const layerId of POI_CATEGORIES[cat]) {
37
+ try {
38
+ if (map.getLayer(layerId)) {
39
+ map.setLayoutProperty(layerId, 'visibility', visibility);
40
+ }
41
+ }
42
+ catch {
43
+ // Layer may not exist in the current map style
44
+ }
45
+ }
46
+ }
47
+ }
48
+ /**
49
+ * Show or hide all POI layers at once.
50
+ *
51
+ * @param map - MapLibre Map instance
52
+ * @param visible - Whether to show or hide all POIs
53
+ *
54
+ * @example
55
+ * setAllPoiVisibility(map, false) // hide everything
56
+ */
57
+ export function setAllPoiVisibility(map, visible) {
58
+ setPoiVisibility(map, Object.keys(POI_CATEGORIES), visible);
59
+ }
@@ -0,0 +1,58 @@
1
+ import type { StyleSpecification } from 'maplibre-gl';
2
+ /**
3
+ * Options for building an AWS Location Service map style URL.
4
+ * All parameters map directly to query parameters supported by the style descriptor endpoint.
5
+ */
6
+ export interface MapStyleOptions {
7
+ /** Color scheme for the map (default: Light). Not applicable to Satellite/Hybrid styles. */
8
+ colorScheme?: 'Light' | 'Dark';
9
+ /** ISO 3166-1 alpha-3 country code for political boundary perspective (e.g. 'IND', 'TUR'). */
10
+ politicalView?: string;
11
+ /** Terrain overlay type. */
12
+ terrain?: 'Hillshade' | 'Terrain3D';
13
+ /** Enable 3D building extrusions. */
14
+ buildings?: 'Buildings3D';
15
+ /** Elevation contour line density. */
16
+ contourDensity?: 'Low' | 'Medium' | 'High';
17
+ /** Enable real-time traffic flow visualization. */
18
+ traffic?: 'All';
19
+ /** Travel mode overlays for routing-specific features. */
20
+ travelModes?: Array<'Truck' | 'Transit'>;
21
+ }
22
+ /**
23
+ * Build a map style descriptor URL for the Location Service API.
24
+ *
25
+ * @param apiUrl - Base URL of the Location Service API
26
+ * @param mapStyle - Map style name (e.g. 'Standard', 'Monochrome', 'Satellite', 'Hybrid')
27
+ * @param options - Optional style parameters
28
+ * @returns Full style descriptor URL
29
+ *
30
+ * @example
31
+ * const url = buildMapStyleUrl(API_URL, 'Standard', { colorScheme: 'Dark', terrain: 'Hillshade' })
32
+ * map.setStyle(url)
33
+ */
34
+ export declare function buildMapStyleUrl(apiUrl: string, mapStyle: string, options?: MapStyleOptions): string;
35
+ /**
36
+ * Fetch the map style descriptor with authentication and apply descriptor-level modifications.
37
+ *
38
+ * Language is applied directly to the descriptor's layer definitions before MapLibre ever
39
+ * processes them, eliminating the visual flash that occurs when modifying layers post-load.
40
+ * All other style parameters (terrain, traffic, etc.) are passed as query parameters.
41
+ *
42
+ * The returned style object can be passed directly to `new maplibregl.Map({ style })` or
43
+ * `map.setStyle()`. Tile, glyph, and sprite requests still go through `transformRequest`
44
+ * for authentication — this only pre-processes the descriptor itself.
45
+ *
46
+ * @param apiUrl - Base URL of the Location Service API
47
+ * @param mapStyle - Map style name (e.g. 'Standard', 'Monochrome', 'Satellite', 'Hybrid')
48
+ * @param getToken - Callback returning the current auth token
49
+ * @param options - Style options; `language` is applied to the descriptor, all others become URL params
50
+ * @returns Modified MapLibre StyleSpecification object
51
+ *
52
+ * @example
53
+ * const style = await fetchMapStyle(API_URL, 'Standard', getToken, { colorScheme: 'Dark', language: 'fr' })
54
+ * const map = new maplibregl.Map({ style, transformRequest: createTransformRequest(API_URL, getToken) })
55
+ */
56
+ export declare function fetchMapStyle(apiUrl: string, mapStyle: string, getToken: () => string | undefined, options?: MapStyleOptions & {
57
+ language?: string;
58
+ }): Promise<StyleSpecification>;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Build a map style descriptor URL for the Location Service API.
3
+ *
4
+ * @param apiUrl - Base URL of the Location Service API
5
+ * @param mapStyle - Map style name (e.g. 'Standard', 'Monochrome', 'Satellite', 'Hybrid')
6
+ * @param options - Optional style parameters
7
+ * @returns Full style descriptor URL
8
+ *
9
+ * @example
10
+ * const url = buildMapStyleUrl(API_URL, 'Standard', { colorScheme: 'Dark', terrain: 'Hillshade' })
11
+ * map.setStyle(url)
12
+ */
13
+ export function buildMapStyleUrl(apiUrl, mapStyle, options = {}) {
14
+ const params = new URLSearchParams();
15
+ if (options.colorScheme)
16
+ params.set('color-scheme', options.colorScheme);
17
+ if (options.politicalView)
18
+ params.set('political-view', options.politicalView);
19
+ if (options.terrain)
20
+ params.set('terrain', options.terrain);
21
+ if (options.buildings)
22
+ params.set('buildings', options.buildings);
23
+ if (options.contourDensity)
24
+ params.set('contour-density', options.contourDensity);
25
+ if (options.traffic)
26
+ params.set('traffic', options.traffic);
27
+ if (options.travelModes?.length)
28
+ params.set('travel-modes', options.travelModes.join(','));
29
+ const qs = params.toString();
30
+ return `${apiUrl}/maps/${mapStyle}/descriptor${qs ? `?${qs}` : ''}`;
31
+ }
32
+ /**
33
+ * Fetch the map style descriptor with authentication and apply descriptor-level modifications.
34
+ *
35
+ * Language is applied directly to the descriptor's layer definitions before MapLibre ever
36
+ * processes them, eliminating the visual flash that occurs when modifying layers post-load.
37
+ * All other style parameters (terrain, traffic, etc.) are passed as query parameters.
38
+ *
39
+ * The returned style object can be passed directly to `new maplibregl.Map({ style })` or
40
+ * `map.setStyle()`. Tile, glyph, and sprite requests still go through `transformRequest`
41
+ * for authentication — this only pre-processes the descriptor itself.
42
+ *
43
+ * @param apiUrl - Base URL of the Location Service API
44
+ * @param mapStyle - Map style name (e.g. 'Standard', 'Monochrome', 'Satellite', 'Hybrid')
45
+ * @param getToken - Callback returning the current auth token
46
+ * @param options - Style options; `language` is applied to the descriptor, all others become URL params
47
+ * @returns Modified MapLibre StyleSpecification object
48
+ *
49
+ * @example
50
+ * const style = await fetchMapStyle(API_URL, 'Standard', getToken, { colorScheme: 'Dark', language: 'fr' })
51
+ * const map = new maplibregl.Map({ style, transformRequest: createTransformRequest(API_URL, getToken) })
52
+ */
53
+ export async function fetchMapStyle(apiUrl, mapStyle, getToken, options = {}) {
54
+ const { language, ...styleOptions } = options;
55
+ const url = buildMapStyleUrl(apiUrl, mapStyle, styleOptions);
56
+ const token = getToken();
57
+ const response = await fetch(url, {
58
+ headers: {
59
+ 'Authorization': `Bearer ${token}`,
60
+ 'Accept': 'application/json',
61
+ }
62
+ });
63
+ if (!response.ok) {
64
+ throw new Error(`Failed to fetch map style: ${response.status} ${response.statusText}`);
65
+ }
66
+ const style = await response.json();
67
+ if (language) {
68
+ applyLanguageToDescriptor(style, language);
69
+ }
70
+ return style;
71
+ }
72
+ /**
73
+ * Apply a preferred language to all symbol layers within a style descriptor object.
74
+ * Mutates the style in place — call before passing to MapLibre.
75
+ */
76
+ function applyLanguageToDescriptor(style, language) {
77
+ const expression = language === 'en'
78
+ ? ['coalesce', ['get', 'name:en'], ['get', 'name']]
79
+ : ['coalesce', ['get', `name:${language}`], ['get', 'name:en'], ['get', 'name']];
80
+ for (const layer of style.layers) {
81
+ if (layer.type === 'symbol') {
82
+ const layout = layer.layout;
83
+ if (layout?.['text-field'] !== undefined) {
84
+ layout['text-field'] = expression;
85
+ }
86
+ }
87
+ }
88
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chaosity/location-client",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Client library for Chaosity Location Service with AWS Location Service compatibility",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",