@chaosity/location-client 0.1.9 → 0.1.11

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/README.md CHANGED
@@ -28,6 +28,9 @@ npm install @chaosity/location-client
28
28
  - **AWS SDK Commands**: Full access to all AWS Location Service commands
29
29
  - **Data Type Utilities**: Built-in GeoJSON conversion utilities
30
30
  - **MapLibre Integration**: Adapter for MapLibre GL Geocoder and `createTransformRequest` helper
31
+ - **Map Style Control**: Fetch and customize map style descriptors with terrain, 3D buildings, traffic, and more
32
+ - **Map Language**: Switch map label language client-side with zero API calls
33
+ - **POI Layer Control**: Toggle point-of-interest categories on/off by layer
31
34
  - **Server Utilities**: `getClientConfig()` with auto-env detection and token caching
32
35
 
33
36
  ## Quick Start
@@ -84,22 +87,61 @@ const response = await client.send(
84
87
 
85
88
  ### MapLibre Map Integration
86
89
 
87
- Use `createTransformRequest` to automatically attach Bearer tokens to map tile requests:
90
+ Use `fetchMapStyle` to fetch a style descriptor with authentication and optional customization, and `createTransformRequest` to attach Bearer tokens to all subsequent tile/glyph/sprite requests:
88
91
 
89
92
  ```typescript
90
- import { createTransformRequest } from '@chaosity/location-client'
93
+ import { fetchMapStyle, createTransformRequest } from '@chaosity/location-client'
91
94
  import maplibregl from 'maplibre-gl'
92
95
 
96
+ const style = await fetchMapStyle(apiUrl, 'Standard', getToken, {
97
+ colorScheme: 'Dark',
98
+ terrain: 'Terrain3D',
99
+ buildings: 'Buildings3D',
100
+ language: 'fr',
101
+ })
102
+
93
103
  const map = new maplibregl.Map({
94
104
  container: 'map',
95
- style: `${apiUrl}/maps/Standard/descriptor`,
105
+ style,
96
106
  center: [-123.12, 49.28],
97
107
  zoom: 10,
108
+ maxPitch: 85,
98
109
  transformRequest: createTransformRequest(apiUrl, getToken),
99
110
  })
100
111
  ```
101
112
 
102
- `createTransformRequest` handles setting the correct `Accept` headers for tiles (protobuf), glyphs, sprites, and style descriptors.
113
+ ### Switching Map Language
114
+
115
+ Change map label language instantly on the client side — no API calls needed:
116
+
117
+ ```typescript
118
+ import { applyMapLanguage } from '@chaosity/location-client'
119
+
120
+ // Apply after the style is loaded
121
+ map.once('style.load', () => applyMapLanguage(map, 'fr'))
122
+
123
+ // Or reapply whenever the user changes language
124
+ applyMapLanguage(map, 'ja')
125
+ ```
126
+
127
+ ### Controlling POI Layers
128
+
129
+ Toggle point-of-interest categories on or off:
130
+
131
+ ```typescript
132
+ import { setPoiVisibility, setAllPoiVisibility, POI_CATEGORIES } from '@chaosity/location-client'
133
+
134
+ // Hide transit POIs
135
+ setPoiVisibility(map, 'transit', false)
136
+
137
+ // Hide multiple categories at once
138
+ setPoiVisibility(map, ['shopping', 'business'], false)
139
+
140
+ // Hide all POIs
141
+ setAllPoiVisibility(map, false)
142
+ ```
143
+
144
+ Available categories: `food_drink`, `entertainment`, `sights`, `transit`, `accommodations`, `leisure`, `shopping`, `business`, `facilities`, `areas`, `parks`.
103
145
 
104
146
  ### MapLibre Geocoder Integration
105
147
 
@@ -172,6 +214,70 @@ import { createTransformRequest } from '@chaosity/location-client'
172
214
  const transformRequest = createTransformRequest(apiUrl, () => currentToken)
173
215
  ```
174
216
 
217
+ #### fetchMapStyle
218
+
219
+ Fetches the map style descriptor with Bearer auth and applies optional language to the descriptor JSON before MapLibre processes it (eliminates the visual flash that occurs when modifying layers post-load).
220
+
221
+ ```typescript
222
+ import { fetchMapStyle } from '@chaosity/location-client'
223
+
224
+ const style = await fetchMapStyle(apiUrl, 'Standard', getToken, {
225
+ colorScheme: 'Dark',
226
+ terrain: 'Terrain3D',
227
+ buildings: 'Buildings3D',
228
+ contourDensity: 'Medium',
229
+ traffic: 'All',
230
+ travelModes: ['Truck', 'Transit'],
231
+ language: 'fr',
232
+ })
233
+
234
+ const map = new maplibregl.Map({ style, transformRequest: createTransformRequest(apiUrl, getToken) })
235
+ ```
236
+
237
+ #### buildMapStyleUrl
238
+
239
+ Builds the style descriptor URL without fetching. Useful when you want to pass the URL directly to MapLibre (e.g. without pre-applying language).
240
+
241
+ ```typescript
242
+ import { buildMapStyleUrl } from '@chaosity/location-client'
243
+
244
+ const url = buildMapStyleUrl(apiUrl, 'Standard', { colorScheme: 'Dark', terrain: 'Hillshade' })
245
+ ```
246
+
247
+ #### MapStyleOptions
248
+
249
+ ```typescript
250
+ interface MapStyleOptions {
251
+ colorScheme?: 'Light' | 'Dark'
252
+ politicalView?: string // ISO 3166-1 alpha-3 (e.g. 'IND', 'TUR')
253
+ terrain?: 'Hillshade' | 'Terrain3D'
254
+ buildings?: 'Buildings3D'
255
+ contourDensity?: 'Medium' // Only 'Medium' is supported by the AWS SDK
256
+ traffic?: 'All'
257
+ travelModes?: Array<'Truck' | 'Transit'>
258
+ }
259
+ ```
260
+
261
+ #### applyMapLanguage
262
+
263
+ Modifies symbol layer `text-field` expressions on an existing map to display labels in the specified language. No API call — operates entirely on the client.
264
+
265
+ ```typescript
266
+ import { applyMapLanguage } from '@chaosity/location-client'
267
+
268
+ applyMapLanguage(map, 'fr')
269
+ ```
270
+
271
+ #### POI Layer Control
272
+
273
+ ```typescript
274
+ import { setPoiVisibility, setAllPoiVisibility, POI_CATEGORIES } from '@chaosity/location-client'
275
+ import type { PoiCategory } from '@chaosity/location-client'
276
+
277
+ setPoiVisibility(map, 'transit', false)
278
+ setAllPoiVisibility(map, false)
279
+ ```
280
+
175
281
  #### Available Commands
176
282
 
177
283
  All AWS Location Service commands from `@aws-sdk/client-geo-places`:
@@ -243,6 +349,14 @@ const connector = new LocationServiceConnector({
243
349
  const result = await connector.send(new SuggestCommand({ QueryText: 'Vancouver' }))
244
350
  ```
245
351
 
352
+ ## Cache-Friendly Position Rounding
353
+
354
+ `BiasPosition` coordinates are automatically rounded to 2 decimal places (~1.1 km grid) before each API request. This maximizes cache hits across nearby users without affecting result quality — bias is approximate by nature.
355
+
356
+ `QueryPosition` (reverse geocode) retains full precision since it represents an exact point the user selected.
357
+
358
+ This is handled transparently in both `GeoPlacesClient` and `LocationServiceConnector` — no action needed in application code.
359
+
246
360
  ## Logging
247
361
 
248
362
  The library uses the `debug` package for optional verbose logging:
@@ -1,5 +1,6 @@
1
1
  import debug from 'debug';
2
2
  import { AutocompleteCommand, GeocodeCommand, GetPlaceCommand, ReverseGeocodeCommand, SearchNearbyCommand, SearchTextCommand, SuggestCommand, } from '@aws-sdk/client-geo-places';
3
+ import { roundPositionFields } from '../utils/roundPosition';
3
4
  const log = debug('location-client:api');
4
5
  const logError = debug('location-client:api:error');
5
6
  // Minification-safe endpoint map — uses constructor identity, not class name strings
@@ -29,7 +30,7 @@ export class GeoPlacesClient {
29
30
  const endpoint = this.getEndpoint(command);
30
31
  const url = `${this.clientConfig.apiUrl}${endpoint}`;
31
32
  const commandName = command.constructor.name;
32
- const input = command.input;
33
+ const input = roundPositionFields(command.input);
33
34
  // Prefer getToken callback (live ref) over static token string
34
35
  const token = this.clientConfig.getToken?.() ?? this.clientConfig.token;
35
36
  log('Sending %s to %s', commandName, endpoint);
@@ -12,8 +12,8 @@ export interface MapStyleOptions {
12
12
  terrain?: 'Hillshade' | 'Terrain3D';
13
13
  /** Enable 3D building extrusions. */
14
14
  buildings?: 'Buildings3D';
15
- /** Elevation contour line density. */
16
- contourDensity?: 'Low' | 'Medium' | 'High';
15
+ /** Elevation contour line density. Only 'Medium' is currently supported by the AWS SDK. */
16
+ contourDensity?: 'Medium';
17
17
  /** Enable real-time traffic flow visualization. */
18
18
  traffic?: 'All';
19
19
  /** Travel mode overlays for routing-specific features. */
@@ -1,6 +1,7 @@
1
1
  import { AutocompleteCommand, GeocodeCommand, GetPlaceCommand, ReverseGeocodeCommand, SearchNearbyCommand, SearchTextCommand, SuggestCommand, } from '@aws-sdk/client-geo-places';
2
2
  import debug from 'debug';
3
3
  import { getClientConfig } from './getClientConfig';
4
+ import { roundPositionFields } from '../utils/roundPosition';
4
5
  const log = debug('location-client:connector');
5
6
  /**
6
7
  * LocationServiceConnector - Server-side connector for Location Service API
@@ -55,7 +56,7 @@ export class LocationServiceConnector {
55
56
  const endpoint = this.getEndpoint(command);
56
57
  const url = `${config.apiUrl}${endpoint}`;
57
58
  const commandName = command.constructor.name;
58
- const input = command.input;
59
+ const input = roundPositionFields(command.input);
59
60
  log('Sending %s request to %s', commandName, endpoint);
60
61
  const startTime = Date.now();
61
62
  // Merge headers: user headers, then system headers override
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Round coordinate arrays in command inputs for better API cache hits.
3
+ *
4
+ * BiasPosition is rounded to 2 decimal places (~1.1 km precision) —
5
+ * sufficient for spatial biasing while maximizing cache reuse across
6
+ * nearby users.
7
+ *
8
+ * QueryPosition (reverse geocode) keeps full precision since it
9
+ * represents an exact point the user clicked or their device reported.
10
+ */
11
+ /**
12
+ * Shallow-clone the input and round position arrays that benefit from caching.
13
+ * Returns the original object if no position fields are present.
14
+ */
15
+ export declare function roundPositionFields<T extends Record<string, any>>(input: T): T;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Round coordinate arrays in command inputs for better API cache hits.
3
+ *
4
+ * BiasPosition is rounded to 2 decimal places (~1.1 km precision) —
5
+ * sufficient for spatial biasing while maximizing cache reuse across
6
+ * nearby users.
7
+ *
8
+ * QueryPosition (reverse geocode) keeps full precision since it
9
+ * represents an exact point the user clicked or their device reported.
10
+ */
11
+ const BIAS_DECIMALS = 2; // ~1.1 km grid
12
+ const BIAS_FACTOR = 10 ** BIAS_DECIMALS;
13
+ /** Known position field names and whether they should be rounded */
14
+ const POSITION_FIELDS = {
15
+ BiasPosition: true, // geocode, autocomplete, search — round for cache
16
+ QueryPosition: false, // reverse geocode — keep full precision
17
+ };
18
+ function roundCoord(value) {
19
+ return Math.round(value * BIAS_FACTOR) / BIAS_FACTOR;
20
+ }
21
+ /**
22
+ * Shallow-clone the input and round position arrays that benefit from caching.
23
+ * Returns the original object if no position fields are present.
24
+ */
25
+ export function roundPositionFields(input) {
26
+ if (!input || typeof input !== 'object')
27
+ return input;
28
+ let modified = false;
29
+ const result = { ...input };
30
+ for (const [field, shouldRound] of Object.entries(POSITION_FIELDS)) {
31
+ const value = result[field];
32
+ if (!shouldRound || !Array.isArray(value) || value.length < 2)
33
+ continue;
34
+ result[field] = value.map(roundCoord);
35
+ modified = true;
36
+ }
37
+ return modified ? result : input;
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chaosity/location-client",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Client library for Chaosity Location Service with AWS Location Service compatibility",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -34,7 +34,7 @@
34
34
  "license": "MIT",
35
35
  "repository": {
36
36
  "type": "git",
37
- "url": "https://github.com/chaosity-io/location-service-client.git"
37
+ "url": "git+https://github.com/chaosity-io/location-service-client.git"
38
38
  },
39
39
  "homepage": "https://github.com/chaosity-io/location-service-client",
40
40
  "bugs": {