@chaosity/location-client-react 0.8.0 → 0.10.0
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
|
@@ -8,6 +8,16 @@ React bindings for [@chaosity/location-client](https://www.npmjs.com/package/@ch
|
|
|
8
8
|
npm install @chaosity/location-client-react @chaosity/location-client
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
`maplibre-gl` is an optional peer, needed by `useMapLanguage` and the map
|
|
12
|
+
examples, at 6.4.1 or a later 6.x release. Earlier releases carry
|
|
13
|
+
[GHSA-jrc7-96c5-q579](https://github.com/advisories/GHSA-jrc7-96c5-q579), an
|
|
14
|
+
XSS in the attribution control, and `@chaosity/location-client` 0.11.0 is the
|
|
15
|
+
first core whose own peer admits 6. Under a bundler, MapLibre 6 runs its worker
|
|
16
|
+
from a file your application serves, so a map needs `setWorkerUrl` once before
|
|
17
|
+
it is built. The examples below serve it from `public/maplibre/`, and
|
|
18
|
+
[The MapLibre worker](https://github.com/chaosity-io/location-service-client#the-maplibre-worker)
|
|
19
|
+
in `@chaosity/location-client`'s README has the copy script and the Vite form.
|
|
20
|
+
|
|
11
21
|
## Quick Start
|
|
12
22
|
|
|
13
23
|
### 1. Create a Server Action to fetch config
|
|
@@ -18,9 +28,16 @@ npm install @chaosity/location-client-react @chaosity/location-client
|
|
|
18
28
|
|
|
19
29
|
import { getClientConfig } from '@chaosity/location-client/server'
|
|
20
30
|
|
|
21
|
-
export async function getLocationConfig() {
|
|
31
|
+
export async function getLocationConfig(request?: { refusedToken?: string }) {
|
|
22
32
|
// Auto-reads LOCATION_API_URL, LOCATION_CLIENT_ID, LOCATION_CLIENT_SECRET
|
|
23
|
-
|
|
33
|
+
const config = await getClientConfig()
|
|
34
|
+
// The API refused this token before its expiry (revoked, or its secret
|
|
35
|
+
// rotated). getClientConfig() keeps one token per application, so replace
|
|
36
|
+
// it, but only when it is the one refused: see Token Refresh, step 5.
|
|
37
|
+
// `request` is optional: it arrives from the browser, and only after a 401.
|
|
38
|
+
return request?.refusedToken === config.token
|
|
39
|
+
? getClientConfig({ forceRefresh: true })
|
|
40
|
+
: config
|
|
24
41
|
}
|
|
25
42
|
```
|
|
26
43
|
|
|
@@ -78,6 +95,11 @@ function SearchComponent() {
|
|
|
78
95
|
}
|
|
79
96
|
```
|
|
80
97
|
|
|
98
|
+
With `@chaosity/location-client` 0.13.0 or later, `client.send` resolves with
|
|
99
|
+
the command's own output type, so the `SuggestCommandOutput` annotation above
|
|
100
|
+
is optional. On an older core, `send` answers `unknown` unless the output type
|
|
101
|
+
is named, as it is here.
|
|
102
|
+
|
|
81
103
|
## Map Utilities
|
|
82
104
|
|
|
83
105
|
### useMapLanguage
|
|
@@ -86,6 +108,9 @@ React hook that keeps map label language in sync. Automatically reapplies after
|
|
|
86
108
|
|
|
87
109
|
```tsx
|
|
88
110
|
import { useMapLanguage } from '@chaosity/location-client-react'
|
|
111
|
+
import * as maplibregl from 'maplibre-gl'
|
|
112
|
+
|
|
113
|
+
maplibregl.setWorkerUrl('/maplibre/maplibre-gl-worker.mjs')
|
|
89
114
|
|
|
90
115
|
function MapComponent() {
|
|
91
116
|
const [mapInstance, setMapInstance] = useState<maplibregl.Map | null>(null)
|
|
@@ -128,7 +153,7 @@ Provides the location client and automatic token refresh to all child components
|
|
|
128
153
|
|
|
129
154
|
**Props:**
|
|
130
155
|
|
|
131
|
-
- `getConfig` — Async function that returns `{ apiUrl: string, token: string, expiresAt?: number }`. Called on mount, whenever the token needs refreshing, and to retry a call that failed (see [Token Refresh](#token-refresh)).
|
|
156
|
+
- `getConfig` — Async function that returns `{ apiUrl: string, token: string, expiresAt?: number }`. Called on mount, whenever the token needs refreshing, and to retry a call that failed (see [Token Refresh](#token-refresh)). After the API refuses a token it is called with `{ refusedToken }`, the token refused; every other call passes nothing. An answer without a non-empty `token` and `apiUrl` is treated as a failure, as a rejection is.
|
|
132
157
|
- `configKey` — Optional. What `getConfig` answers for, such as an organisation or application id. When it changes, the provider drops the old client, token and `apiUrl`, calls `getConfig` again and hands out a new client, without remounting its children.
|
|
133
158
|
- `children` — Child components.
|
|
134
159
|
|
|
@@ -202,8 +227,22 @@ The provider owns the token lifecycle. There is nothing to manage manually.
|
|
|
202
227
|
until the timer next comes around: for a token with 14 minutes left, 14
|
|
203
228
|
minutes of a broken page. The core added this in 0.7.0, so every core this
|
|
204
229
|
package's peer range admits has it.
|
|
230
|
+
|
|
231
|
+
Since 0.10.0 that refresh calls `getConfig({ refusedToken })`. Your server
|
|
232
|
+
has to act on it: `getClientConfig()` keeps one token per application and,
|
|
233
|
+
asked again, hands back the one just refused, so nothing is retried until
|
|
234
|
+
its cache comes round on its own (measured: almost ten minutes). Replace the
|
|
235
|
+
cached token only when it is the refused one, as the Quick Start does: that
|
|
236
|
+
mints once per refused token, however many visitors report it, and nothing
|
|
237
|
+
for a report of any other token. It does not stop a visitor echoing the
|
|
238
|
+
token it was just handed to make your server mint again; rate-limit the
|
|
239
|
+
action if that matters.
|
|
240
|
+
|
|
205
241
|
6. Concurrent refreshes are deduplicated — everything waiting shares one call to
|
|
206
|
-
`getConfig`.
|
|
242
|
+
`getConfig`. A 401 that lands while a scheduled refresh is in flight shares
|
|
243
|
+
that call too, which names no token, so the refused one is named on the
|
|
244
|
+
next 401: at the next `send()` on a core below 0.12.0, and after the core's
|
|
245
|
+
30-second hold from 0.12.0.
|
|
207
246
|
7. A failed `getConfig` is retried on the provider's own timer, backing off
|
|
208
247
|
exponentially from 1 to 30 seconds, with jitter. When `getConfig` rejects
|
|
209
248
|
with an error that has `retryAfterMs` (milliseconds), it waits that long
|
|
@@ -217,8 +256,13 @@ The provider owns the token lifecycle. There is nothing to manage manually.
|
|
|
217
256
|
there:
|
|
218
257
|
|
|
219
258
|
```ts
|
|
220
|
-
async function getConfig() {
|
|
221
|
-
|
|
259
|
+
async function getConfig(request?: { refusedToken: string }) {
|
|
260
|
+
// In the body, not the URL, so the token stays out of access logs.
|
|
261
|
+
const res = await fetch('/api/location-token', {
|
|
262
|
+
method: 'POST',
|
|
263
|
+
headers: { 'content-type': 'application/json' },
|
|
264
|
+
body: JSON.stringify(request ?? {}),
|
|
265
|
+
})
|
|
222
266
|
if (!res.ok) {
|
|
223
267
|
const retryAfter = Number(res.headers.get('retry-after'))
|
|
224
268
|
throw Object.assign(new Error(`token route answered ${res.status}`), {
|
|
@@ -260,8 +304,14 @@ import {
|
|
|
260
304
|
fetchMapStyle,
|
|
261
305
|
createTransformRequest,
|
|
262
306
|
} from '@chaosity/location-client'
|
|
263
|
-
import maplibregl from 'maplibre-gl'
|
|
307
|
+
import * as maplibregl from 'maplibre-gl'
|
|
308
|
+
import 'maplibre-gl/dist/maplibre-gl.css'
|
|
264
309
|
import MaplibreGeocoder from '@maplibre/maplibre-gl-geocoder'
|
|
310
|
+
import '@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css'
|
|
311
|
+
|
|
312
|
+
// Once, before the first map: the worker file the application serves (see
|
|
313
|
+
// Installation).
|
|
314
|
+
maplibregl.setWorkerUrl('/maplibre/maplibre-gl-worker.mjs')
|
|
265
315
|
|
|
266
316
|
export default function MapComponent() {
|
|
267
317
|
const mapContainer = useRef<HTMLDivElement>(null)
|
|
@@ -300,6 +350,8 @@ export default function MapComponent() {
|
|
|
300
350
|
'top-right',
|
|
301
351
|
)
|
|
302
352
|
|
|
353
|
+
// Type-checks with @chaosity/location-client 0.13.0 or later. An older
|
|
354
|
+
// core types GeoPlaces's client as GeoPlacesClient, and reports TS2345.
|
|
303
355
|
const geoPlaces = new GeoPlaces(client, instance)
|
|
304
356
|
const geocoder = new MaplibreGeocoder(geoPlaces, {
|
|
305
357
|
maplibregl,
|
|
@@ -475,6 +527,11 @@ const response: SuggestCommandOutput = await client!.send(
|
|
|
475
527
|
)
|
|
476
528
|
```
|
|
477
529
|
|
|
530
|
+
Every `send` example in this README names the output type, so it compiles on
|
|
531
|
+
every core the peer range admits. From `@chaosity/location-client` 0.13.0 the
|
|
532
|
+
annotation is optional: `send` resolves with the command's own output type,
|
|
533
|
+
and the core's `CommandOutput<C>` names it when you need it.
|
|
534
|
+
|
|
478
535
|
## License
|
|
479
536
|
|
|
480
537
|
MIT
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ClientConfig, VerifyAddressResponse } from '@chaosity/location-client';
|
|
2
|
-
import { type AppConfigClaims } from '@chaosity/location-client';
|
|
2
|
+
import { type AppConfigClaims, GeoPlacesClient } from '@chaosity/location-client';
|
|
3
3
|
import type { ReactNode } from 'react';
|
|
4
4
|
/**
|
|
5
5
|
* Per-request transport options.
|
|
@@ -36,7 +36,16 @@ export interface LocationClient {
|
|
|
36
36
|
readonly config: {
|
|
37
37
|
serviceId: string;
|
|
38
38
|
};
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* The core's own `send`, overloads and all, not a copy of it: from core
|
|
41
|
+
* 0.13.0, `await client.send(new AutocompleteCommand(…))` is an
|
|
42
|
+
* `AutocompleteCommandOutput` with nothing to annotate (core #68). A copy
|
|
43
|
+
* of the old `send<TInput, TOutput>` kept answering `unknown`, and nothing
|
|
44
|
+
* caught it — that one signature and the core's pair of overloads are
|
|
45
|
+
* assignable to each other both ways. Below 0.13.0 it is the core's old
|
|
46
|
+
* signature, as before.
|
|
47
|
+
*/
|
|
48
|
+
send: GeoPlacesClient['send'];
|
|
40
49
|
/**
|
|
41
50
|
* Verify a PlaceId through `POST /address/verify`: the full place record plus
|
|
42
51
|
* `verified`, the one Places result an integrator may store (#26). A
|
|
@@ -86,7 +95,32 @@ interface LocationClientContextValue {
|
|
|
86
95
|
}
|
|
87
96
|
export interface LocationClientProviderProps {
|
|
88
97
|
children: ReactNode;
|
|
89
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Where the token and `apiUrl` come from: usually a server action returning
|
|
100
|
+
* `getClientConfig()`.
|
|
101
|
+
*
|
|
102
|
+
* After the API refuses a token before its `exp` (a revoked token, or a
|
|
103
|
+
* rotated secret), it is asked with `{ refusedToken }`, the token refused
|
|
104
|
+
* (#43). `getClientConfig()` caches one token per application, so a server
|
|
105
|
+
* that ignores this hands the refused token back, and the page stays broken
|
|
106
|
+
* until that cache comes round on its own. Ask for a new one only when the
|
|
107
|
+
* cached token IS the refused one:
|
|
108
|
+
*
|
|
109
|
+
* return request?.refusedToken === config.token
|
|
110
|
+
* ? getClientConfig({ forceRefresh: true })
|
|
111
|
+
* : config
|
|
112
|
+
*
|
|
113
|
+
* That mints once per refused token, and nothing for a report of any other.
|
|
114
|
+
* It does not stop a caller echoing the token it was just handed, so a
|
|
115
|
+
* server worried about that rate-limits the call. Every other call passes
|
|
116
|
+
* nothing, and a `getConfig` that ignores the argument works as before.
|
|
117
|
+
*
|
|
118
|
+
* An answer without a non-empty `token` and `apiUrl` is taken as a failure
|
|
119
|
+
* (#39), as a rejection is.
|
|
120
|
+
*/
|
|
121
|
+
getConfig: (request?: {
|
|
122
|
+
refusedToken: string;
|
|
123
|
+
}) => Promise<ClientConfig & {
|
|
90
124
|
expiresAt?: number;
|
|
91
125
|
}>;
|
|
92
126
|
/**
|
|
@@ -48,6 +48,7 @@ function retryAfterOf(err) {
|
|
|
48
48
|
?.retryAfterMs;
|
|
49
49
|
return typeof ms === 'number' && ms > 0 ? ms : undefined;
|
|
50
50
|
}
|
|
51
|
+
const isFilled = (value) => typeof value === 'string' && value.length > 0;
|
|
51
52
|
function overrides(trigger, hold) {
|
|
52
53
|
if (trigger === 'scheduled')
|
|
53
54
|
return true;
|
|
@@ -204,7 +205,9 @@ function LocationClientProvider({ children, getConfig, configKey, }) {
|
|
|
204
205
|
*
|
|
205
206
|
* The client awaits this after a 401 and retries the request once with
|
|
206
207
|
* what it returns; the same token, or nothing, means no retry, so a
|
|
207
|
-
* doomed request is never sent — or billed — twice.
|
|
208
|
+
* doomed request is never sent — or billed — twice. The `rejected`
|
|
209
|
+
* trigger names the refused token to `getConfig` (#43): a server that
|
|
210
|
+
* caches one token returns it again unless told which one was refused.
|
|
208
211
|
*
|
|
209
212
|
* @chaosity/location-client 0.8.0 and later also calls it BEFORE the
|
|
210
213
|
* first send when it holds no token at all. Here that means this client
|
|
@@ -232,6 +235,9 @@ function LocationClientProvider({ children, getConfig, configKey, }) {
|
|
|
232
235
|
// this provider would have been silently discarded.
|
|
233
236
|
const client = {
|
|
234
237
|
config: baseClient.config,
|
|
238
|
+
// Typed by `LocationClient` above, so callers see the core's overloads
|
|
239
|
+
// and never this signature: a literal has no overload syntax, and one
|
|
240
|
+
// generic body with the cast satisfies both (core #68).
|
|
235
241
|
async send(command, options) {
|
|
236
242
|
await ready();
|
|
237
243
|
return baseClient.send(command, options);
|
|
@@ -284,10 +290,31 @@ function LocationClientProvider({ children, getConfig, configKey, }) {
|
|
|
284
290
|
: Promise.reject(hold.error);
|
|
285
291
|
}
|
|
286
292
|
log('Asking getConfig (%s)', trigger);
|
|
293
|
+
// The token the API refused, so a server that caches one can replace
|
|
294
|
+
// exactly that one (#43). Named on no other trigger, where the call
|
|
295
|
+
// stays argument-less. A `rejected` call that finds an attempt in
|
|
296
|
+
// flight joins it above and names nothing, and the next 401 names it:
|
|
297
|
+
// at the next send below core 0.12.0, and after that core's 30 s hold
|
|
298
|
+
// on the refused token from 0.12.0. The core's `refreshToken` takes no
|
|
299
|
+
// argument, so `state.token` stands for the token it sent.
|
|
300
|
+
const refused = trigger === 'rejected' ? state.token : undefined;
|
|
301
|
+
const request = refused
|
|
302
|
+
? [{ refusedToken: refused }]
|
|
303
|
+
: [];
|
|
287
304
|
const attempt = (async () => {
|
|
288
305
|
let cfg;
|
|
289
306
|
try {
|
|
290
|
-
cfg = await getConfigRef.current();
|
|
307
|
+
cfg = await getConfigRef.current(...request);
|
|
308
|
+
// A token route's error body passed through `res.json()` resolves
|
|
309
|
+
// too (#39). Installing it published a client for no URL, and an
|
|
310
|
+
// `error` of null, so it fails here as a rejection does.
|
|
311
|
+
const missing = !isFilled(cfg?.token)
|
|
312
|
+
? 'a token'
|
|
313
|
+
: !isFilled(cfg?.apiUrl)
|
|
314
|
+
? 'an apiUrl'
|
|
315
|
+
: null;
|
|
316
|
+
if (missing)
|
|
317
|
+
throw new Error(`getConfig resolved without ${missing}`);
|
|
291
318
|
}
|
|
292
319
|
catch (err) {
|
|
293
320
|
if (configRef.current !== state)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ClientConfig, VerifyAddressResponse } from '@chaosity/location-client';
|
|
2
|
-
import { type AppConfigClaims } from '@chaosity/location-client';
|
|
2
|
+
import { type AppConfigClaims, GeoPlacesClient } from '@chaosity/location-client';
|
|
3
3
|
import type { ReactNode } from 'react';
|
|
4
4
|
/**
|
|
5
5
|
* Per-request transport options.
|
|
@@ -36,7 +36,16 @@ export interface LocationClient {
|
|
|
36
36
|
readonly config: {
|
|
37
37
|
serviceId: string;
|
|
38
38
|
};
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* The core's own `send`, overloads and all, not a copy of it: from core
|
|
41
|
+
* 0.13.0, `await client.send(new AutocompleteCommand(…))` is an
|
|
42
|
+
* `AutocompleteCommandOutput` with nothing to annotate (core #68). A copy
|
|
43
|
+
* of the old `send<TInput, TOutput>` kept answering `unknown`, and nothing
|
|
44
|
+
* caught it — that one signature and the core's pair of overloads are
|
|
45
|
+
* assignable to each other both ways. Below 0.13.0 it is the core's old
|
|
46
|
+
* signature, as before.
|
|
47
|
+
*/
|
|
48
|
+
send: GeoPlacesClient['send'];
|
|
40
49
|
/**
|
|
41
50
|
* Verify a PlaceId through `POST /address/verify`: the full place record plus
|
|
42
51
|
* `verified`, the one Places result an integrator may store (#26). A
|
|
@@ -86,7 +95,32 @@ interface LocationClientContextValue {
|
|
|
86
95
|
}
|
|
87
96
|
export interface LocationClientProviderProps {
|
|
88
97
|
children: ReactNode;
|
|
89
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Where the token and `apiUrl` come from: usually a server action returning
|
|
100
|
+
* `getClientConfig()`.
|
|
101
|
+
*
|
|
102
|
+
* After the API refuses a token before its `exp` (a revoked token, or a
|
|
103
|
+
* rotated secret), it is asked with `{ refusedToken }`, the token refused
|
|
104
|
+
* (#43). `getClientConfig()` caches one token per application, so a server
|
|
105
|
+
* that ignores this hands the refused token back, and the page stays broken
|
|
106
|
+
* until that cache comes round on its own. Ask for a new one only when the
|
|
107
|
+
* cached token IS the refused one:
|
|
108
|
+
*
|
|
109
|
+
* return request?.refusedToken === config.token
|
|
110
|
+
* ? getClientConfig({ forceRefresh: true })
|
|
111
|
+
* : config
|
|
112
|
+
*
|
|
113
|
+
* That mints once per refused token, and nothing for a report of any other.
|
|
114
|
+
* It does not stop a caller echoing the token it was just handed, so a
|
|
115
|
+
* server worried about that rate-limits the call. Every other call passes
|
|
116
|
+
* nothing, and a `getConfig` that ignores the argument works as before.
|
|
117
|
+
*
|
|
118
|
+
* An answer without a non-empty `token` and `apiUrl` is taken as a failure
|
|
119
|
+
* (#39), as a rejection is.
|
|
120
|
+
*/
|
|
121
|
+
getConfig: (request?: {
|
|
122
|
+
refusedToken: string;
|
|
123
|
+
}) => Promise<ClientConfig & {
|
|
90
124
|
expiresAt?: number;
|
|
91
125
|
}>;
|
|
92
126
|
/**
|
|
@@ -41,6 +41,7 @@ function retryAfterOf(err) {
|
|
|
41
41
|
?.retryAfterMs;
|
|
42
42
|
return typeof ms === 'number' && ms > 0 ? ms : undefined;
|
|
43
43
|
}
|
|
44
|
+
const isFilled = (value) => typeof value === 'string' && value.length > 0;
|
|
44
45
|
function overrides(trigger, hold) {
|
|
45
46
|
if (trigger === 'scheduled')
|
|
46
47
|
return true;
|
|
@@ -197,7 +198,9 @@ export function LocationClientProvider({ children, getConfig, configKey, }) {
|
|
|
197
198
|
*
|
|
198
199
|
* The client awaits this after a 401 and retries the request once with
|
|
199
200
|
* what it returns; the same token, or nothing, means no retry, so a
|
|
200
|
-
* doomed request is never sent — or billed — twice.
|
|
201
|
+
* doomed request is never sent — or billed — twice. The `rejected`
|
|
202
|
+
* trigger names the refused token to `getConfig` (#43): a server that
|
|
203
|
+
* caches one token returns it again unless told which one was refused.
|
|
201
204
|
*
|
|
202
205
|
* @chaosity/location-client 0.8.0 and later also calls it BEFORE the
|
|
203
206
|
* first send when it holds no token at all. Here that means this client
|
|
@@ -225,6 +228,9 @@ export function LocationClientProvider({ children, getConfig, configKey, }) {
|
|
|
225
228
|
// this provider would have been silently discarded.
|
|
226
229
|
const client = {
|
|
227
230
|
config: baseClient.config,
|
|
231
|
+
// Typed by `LocationClient` above, so callers see the core's overloads
|
|
232
|
+
// and never this signature: a literal has no overload syntax, and one
|
|
233
|
+
// generic body with the cast satisfies both (core #68).
|
|
228
234
|
async send(command, options) {
|
|
229
235
|
await ready();
|
|
230
236
|
return baseClient.send(command, options);
|
|
@@ -277,10 +283,31 @@ export function LocationClientProvider({ children, getConfig, configKey, }) {
|
|
|
277
283
|
: Promise.reject(hold.error);
|
|
278
284
|
}
|
|
279
285
|
log('Asking getConfig (%s)', trigger);
|
|
286
|
+
// The token the API refused, so a server that caches one can replace
|
|
287
|
+
// exactly that one (#43). Named on no other trigger, where the call
|
|
288
|
+
// stays argument-less. A `rejected` call that finds an attempt in
|
|
289
|
+
// flight joins it above and names nothing, and the next 401 names it:
|
|
290
|
+
// at the next send below core 0.12.0, and after that core's 30 s hold
|
|
291
|
+
// on the refused token from 0.12.0. The core's `refreshToken` takes no
|
|
292
|
+
// argument, so `state.token` stands for the token it sent.
|
|
293
|
+
const refused = trigger === 'rejected' ? state.token : undefined;
|
|
294
|
+
const request = refused
|
|
295
|
+
? [{ refusedToken: refused }]
|
|
296
|
+
: [];
|
|
280
297
|
const attempt = (async () => {
|
|
281
298
|
let cfg;
|
|
282
299
|
try {
|
|
283
|
-
cfg = await getConfigRef.current();
|
|
300
|
+
cfg = await getConfigRef.current(...request);
|
|
301
|
+
// A token route's error body passed through `res.json()` resolves
|
|
302
|
+
// too (#39). Installing it published a client for no URL, and an
|
|
303
|
+
// `error` of null, so it fails here as a rejection does.
|
|
304
|
+
const missing = !isFilled(cfg?.token)
|
|
305
|
+
? 'a token'
|
|
306
|
+
: !isFilled(cfg?.apiUrl)
|
|
307
|
+
? 'an apiUrl'
|
|
308
|
+
: null;
|
|
309
|
+
if (missing)
|
|
310
|
+
throw new Error(`getConfig resolved without ${missing}`);
|
|
284
311
|
}
|
|
285
312
|
catch (err) {
|
|
286
313
|
if (configRef.current !== state)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chaosity/location-client-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "React bindings for Chaosity Location Service client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@chaosity/location-client": ">=0.10.0",
|
|
42
|
-
"maplibre-gl": "^
|
|
42
|
+
"maplibre-gl": "^6.4.1",
|
|
43
43
|
"react": "^19.0.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependenciesMeta": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@chaosity/location-client": "^0.
|
|
51
|
+
"@chaosity/location-client": "^0.13.0",
|
|
52
52
|
"@eslint/js": "^10.0.1",
|
|
53
53
|
"@testing-library/react": "^16.0.0",
|
|
54
54
|
"@testing-library/user-event": "^14.0.0",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"eslint": "^10.1.0",
|
|
59
59
|
"happy-dom": "^20.11.6",
|
|
60
60
|
"husky": "^9.0.0",
|
|
61
|
-
"maplibre-gl": "^
|
|
61
|
+
"maplibre-gl": "^6.4.1",
|
|
62
62
|
"prettier": "^3.8.1",
|
|
63
63
|
"prettier-plugin-organize-imports": "^4.3.0",
|
|
64
64
|
"react": "^19.0.0",
|