@tileflow/react-native 0.1.0-alpha.7 → 0.1.0-alpha.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.
@@ -1,4 +1,4 @@
1
- import { M as MapView, a as MapViewChangeEvent, b as MapInitialViewInputs, c as MapCameraProps } from '../contract-BaK24QZD.js';
1
+ import { M as MapView, a as MapViewChangeEvent, b as MapInitialViewInputs, c as MapCameraProps } from '../contract-BWCbfMOx.js';
2
2
  import '@maplibre/maplibre-react-native';
3
3
  import 'react';
4
4
  import 'react-native';
@@ -1,4 +1,4 @@
1
- import { b as MapInitialViewInputs, M as MapView } from '../contract-BaK24QZD.js';
1
+ import { b as MapInitialViewInputs, M as MapView } from '../contract-BWCbfMOx.js';
2
2
  import '@maplibre/maplibre-react-native';
3
3
  import 'react';
4
4
  import 'react-native';
@@ -9,6 +9,7 @@ var messages = {
9
9
  DUPLICATE_ANNOTATION_ID: "Annotation IDs must be unique.",
10
10
  INVALID_FIELD: "An interaction field is invalid.",
11
11
  INVALID_ANNOTATION: "An annotation is invalid.",
12
+ INVALID_DATA_LAYER: "A data source or overlay is invalid.",
12
13
  INVALID_DOCUMENT: "The interaction document is invalid.",
13
14
  LIMIT_EXCEEDED: "The portable interaction limit was exceeded.",
14
15
  MISSING_VIEW: "The interaction view is unavailable.",
@@ -11,6 +11,7 @@ type NativeMapAdmissionInput = Omit<SessionInput, 'fetch' | 'sessionIdFactory'>
11
11
  onSessionError?: (error: Readonly<{
12
12
  code: HostedNativeSessionErrorCode;
13
13
  kind: HostedNativeSessionErrorKind;
14
+ reason?: string;
14
15
  }>) => void;
15
16
  }>;
16
17
  type NativeMapAdmission = Readonly<{
@@ -343,6 +343,8 @@ var RETRY_LIMIT_MS = 6e4;
343
343
  var RETRY_AFTER_LIMIT_MS = 15 * 60 * 1e3;
344
344
  var RETRY_AFTER_SECONDS = /^\d{1,10}$/u;
345
345
  var QUOTA_CODES = /* @__PURE__ */ new Set(["COMMERCIAL_MAP_LIMIT_REACHED", "COMMERCIAL_SPENDING_LIMIT_REACHED"]);
346
+ var SERVICE_CODE = /^[A-Z][A-Z0-9_]{0,63}$/u;
347
+ var SERVICE_CODE_BODY_LIMIT = 4096;
346
348
  var MOBILE_CREDENTIAL = /^tf_public_[0-9a-f]{48}$/u;
347
349
  var MAP_ID = /^map_[A-Za-z0-9_-]{16}$/u;
348
350
  var CREDENTIAL_ID = /^key_[A-Za-z0-9_-]{8,80}$/u;
@@ -386,7 +388,8 @@ var TERMINAL_CODES = /* @__PURE__ */ new Set([
386
388
  "NATIVE_SESSION_CREDENTIAL_REJECTED",
387
389
  "NATIVE_SESSION_MAP_MISMATCH",
388
390
  "NATIVE_SESSION_MAP_NOT_FOUND",
389
- "NATIVE_SESSION_QUOTA_EXCEEDED"
391
+ "NATIVE_SESSION_QUOTA_EXCEEDED",
392
+ "NATIVE_SESSION_REJECTED"
390
393
  ]);
391
394
  var ERROR_MESSAGES = {
392
395
  NATIVE_SESSION_INPUT_INVALID: "Native session configuration is invalid.",
@@ -405,13 +408,16 @@ var ERROR_MESSAGES = {
405
408
  NATIVE_SESSION_DISPOSED: "Native session controller is disposed."
406
409
  };
407
410
  var HostedNativeSessionError = class extends Error {
408
- constructor(code) {
411
+ constructor(code, reason) {
409
412
  super(ERROR_MESSAGES[code]);
410
413
  __publicField(this, "code");
411
414
  __publicField(this, "kind");
412
415
  this.name = "HostedNativeSessionError";
413
416
  this.code = code;
414
417
  this.kind = errorKind(code);
418
+ if (code === "NATIVE_SESSION_REJECTED" && typeof reason === "string" && SERVICE_CODE.test(reason)) {
419
+ this.reason = reason;
420
+ }
415
421
  }
416
422
  };
417
423
  function createHostedNativeSessionController(input) {
@@ -540,10 +546,10 @@ function createHostedNativeSessionController(input) {
540
546
  if (retryAt === null || at >= retryAt) failures = Math.min(failures + 1, 16);
541
547
  const backoff = Math.min(RETRY_INITIAL_MS * 2 ** (failures - 1), RETRY_LIMIT_MS);
542
548
  retryAt = Math.max(retryAt ?? at, at + Math.max(backoff, retryAfterDelays.get(error) ?? 0));
543
- retryError = Object.freeze({ code: error.code, kind: error.kind });
549
+ retryError = safeError(error);
544
550
  }
545
551
  function rotateIfRequired(at) {
546
- if (terminal) throw new HostedNativeSessionError(terminal.code);
552
+ if (terminal) throw errorFrom(terminal);
547
553
  if (!activeSession || binding.kind !== "hosted") return;
548
554
  if (at - activeSession.startedAt < ROTATION_AGE_MS && activeSession.requestCount < ROTATION_REQUEST_LIMIT) {
549
555
  return;
@@ -577,7 +583,7 @@ function createHostedNativeSessionController(input) {
577
583
  return current;
578
584
  }
579
585
  async function ensureAuthority(session, at) {
580
- if (terminal) throw new HostedNativeSessionError(terminal.code);
586
+ if (terminal) throw errorFrom(terminal);
581
587
  if (session.authority && session.authority.clockEpoch === clock.epoch && session.authority.validUntil - at > REFRESH_MARGIN_MS) {
582
588
  return { authority: session.authority, session };
583
589
  }
@@ -589,7 +595,7 @@ function createHostedNativeSessionController(input) {
589
595
  if (session.authority && session.authority.clockEpoch === clock.epoch && session.authority.validUntil > at) {
590
596
  return { authority: session.authority, session };
591
597
  }
592
- throw new HostedNativeSessionError(retryError.code);
598
+ throw errorFrom(retryError);
593
599
  }
594
600
  const operationBinding = binding;
595
601
  const abort = new SessionAbortController();
@@ -616,14 +622,16 @@ function createHostedNativeSessionController(input) {
616
622
  const normalized = abort.signal.aborted ? abort.error() : normalizeError(error);
617
623
  const target = latestSession(session);
618
624
  if (normalized.kind === "terminal" && binding === operationBinding && !terminal) {
619
- const failure = Object.freeze({ code: normalized.code, kind: normalized.kind });
625
+ const failure = safeError(normalized);
620
626
  terminal = failure;
621
627
  const rejectedSession = activeSession;
622
628
  if (rejectedSession) {
623
629
  rejectedSession.authority = null;
624
630
  rejectedSession.error = failure;
625
631
  }
626
- for (const pending of [...operations]) pending.abort(failure.code);
632
+ for (const pending of [...operations]) {
633
+ pending.abort(failure.code, failure.reason);
634
+ }
627
635
  if (binding === operationBinding && rejectedSession) {
628
636
  publishSession(rejectedSession, "error", failure);
629
637
  }
@@ -632,7 +640,7 @@ function createHostedNativeSessionController(input) {
632
640
  delayRetry(normalized);
633
641
  }
634
642
  if (normalized.code !== "NATIVE_SESSION_REPLACED" && normalized.code !== "NATIVE_SESSION_DISPOSED") {
635
- target.error = Object.freeze({ code: normalized.code, kind: normalized.kind });
643
+ target.error = safeError(normalized);
636
644
  publishSession(target, "error", target.error);
637
645
  }
638
646
  throw normalized;
@@ -658,7 +666,7 @@ function createHostedNativeSessionController(input) {
658
666
  if (abort.signal.aborted) throw abort.error();
659
667
  const expectedSurfaceId = session.authority?.public.surfaceId ?? session.requestedSurfaceId;
660
668
  const response = await fetchResponse(hostedBinding, session, expectedSurfaceId, abort);
661
- const source = await readBoundedResponse(response, abort);
669
+ const { source, size } = await readBoundedResponse(response, abort);
662
670
  let body;
663
671
  try {
664
672
  body = source.length ? JSON.parse(source) : null;
@@ -668,14 +676,15 @@ function createHostedNativeSessionController(input) {
668
676
  }
669
677
  body = null;
670
678
  }
671
- if (response.status === 409 && allowRestart && isExactRestart(body, session.sessionId)) {
679
+ if (response.status === 409 && isExactRestart(body, session.sessionId)) {
680
+ if (!allowRestart) throw new HostedNativeSessionError("NATIVE_SESSION_UNAVAILABLE");
672
681
  assertCurrentSession(session, hostedBinding);
673
682
  const replacement = redirectSession(session, readClock());
674
683
  if (abort.signal.aborted) throw abort.error();
675
684
  return bootstrap(replacement, hostedBinding, abort, false, false);
676
685
  }
677
686
  if (response.status !== 201) {
678
- const failure = statusError(response.status, body);
687
+ const failure = statusError(response.status, body, size);
679
688
  const delay = retryAfterMs(response.headers, now);
680
689
  if (delay !== null) retryAfterDelays.set(failure, delay);
681
690
  throw failure;
@@ -813,7 +822,7 @@ function createHostedNativeSessionController(input) {
813
822
  if (bindingGeneration !== expectedGeneration) {
814
823
  throw new HostedNativeSessionError("NATIVE_SESSION_REPLACED");
815
824
  }
816
- if (terminal) throw new HostedNativeSessionError(terminal.code);
825
+ if (terminal) throw errorFrom(terminal);
817
826
  checkedAt = readClock();
818
827
  if (resolved.authority.clockEpoch === clock.epoch && resolved.authority.validUntil > checkedAt) {
819
828
  admittedAuthorities.set(resolved.authority.public, resolved.authority);
@@ -888,7 +897,7 @@ function createHostedNativeSessionController(input) {
888
897
  if (disposed) throw new HostedNativeSessionError("NATIVE_SESSION_DISPOSED");
889
898
  lifecycle = "foreground";
890
899
  if (terminal) {
891
- const error = new HostedNativeSessionError(terminal.code);
900
+ const error = errorFrom(terminal);
892
901
  publish(currentSnapshot());
893
902
  throw error;
894
903
  }
@@ -1161,7 +1170,7 @@ async function readBoundedResponse(response, abort) {
1161
1170
  bytes.set(chunk, offset);
1162
1171
  offset += chunk.byteLength;
1163
1172
  }
1164
- return decodeUtf8(bytes);
1173
+ return { source: decodeUtf8(bytes), size };
1165
1174
  }
1166
1175
  function decodeUtf8(bytes) {
1167
1176
  let result = "";
@@ -1209,7 +1218,7 @@ function decodeUtf8(bytes) {
1209
1218
  function hasNoStore(value) {
1210
1219
  return typeof value === "string" && value.split(",").some((part) => part.trim().toLowerCase() === "no-store");
1211
1220
  }
1212
- function statusError(status, body) {
1221
+ function statusError(status, body, size) {
1213
1222
  if (status === 401) return new HostedNativeSessionError("NATIVE_SESSION_CREDENTIAL_REJECTED");
1214
1223
  if (status === 403) return new HostedNativeSessionError("NATIVE_SESSION_MAP_MISMATCH");
1215
1224
  if (status === 404) return new HostedNativeSessionError("NATIVE_SESSION_MAP_NOT_FOUND");
@@ -1221,7 +1230,21 @@ function statusError(status, body) {
1221
1230
  if (status === 408 || status >= 500 && status <= 599) {
1222
1231
  return new HostedNativeSessionError("NATIVE_SESSION_UNAVAILABLE");
1223
1232
  }
1224
- return new HostedNativeSessionError("NATIVE_SESSION_REJECTED");
1233
+ if (status >= 400 && status <= 499) {
1234
+ return new HostedNativeSessionError(
1235
+ "NATIVE_SESSION_REJECTED",
1236
+ size <= SERVICE_CODE_BODY_LIMIT && isRecord(body) && typeof body.code === "string" ? body.code : void 0
1237
+ );
1238
+ }
1239
+ return new HostedNativeSessionError("NATIVE_SESSION_RESPONSE_INVALID");
1240
+ }
1241
+ function safeError(error) {
1242
+ return Object.freeze(
1243
+ error.reason === void 0 ? { code: error.code, kind: error.kind } : { code: error.code, kind: error.kind, reason: error.reason }
1244
+ );
1245
+ }
1246
+ function errorFrom(error) {
1247
+ return new HostedNativeSessionError(error.code, error.reason);
1225
1248
  }
1226
1249
  var retryAfterDelays = /* @__PURE__ */ new WeakMap();
1227
1250
  function retryAfterMs(headers, now) {
@@ -1271,12 +1294,13 @@ async function cancelResponse(response) {
1271
1294
  } catch {
1272
1295
  }
1273
1296
  }
1274
- var _aborted, _code, _listeners;
1297
+ var _aborted, _code, _reason, _listeners;
1275
1298
  var SessionAbortController = class {
1276
1299
  constructor() {
1277
1300
  __publicField(this, "signal");
1278
1301
  __privateAdd(this, _aborted, false);
1279
1302
  __privateAdd(this, _code, "NATIVE_SESSION_REPLACED");
1303
+ __privateAdd(this, _reason);
1280
1304
  __privateAdd(this, _listeners, /* @__PURE__ */ new Set());
1281
1305
  const isAborted = () => __privateGet(this, _aborted);
1282
1306
  this.signal = Object.freeze({
@@ -1291,9 +1315,10 @@ var SessionAbortController = class {
1291
1315
  }
1292
1316
  });
1293
1317
  }
1294
- abort(code) {
1318
+ abort(code, reason) {
1295
1319
  if (__privateGet(this, _aborted)) return;
1296
1320
  __privateSet(this, _code, code);
1321
+ __privateSet(this, _reason, reason);
1297
1322
  __privateSet(this, _aborted, true);
1298
1323
  for (const listener of [...__privateGet(this, _listeners)]) {
1299
1324
  try {
@@ -1304,11 +1329,12 @@ var SessionAbortController = class {
1304
1329
  __privateGet(this, _listeners).clear();
1305
1330
  }
1306
1331
  error() {
1307
- return new HostedNativeSessionError(__privateGet(this, _code));
1332
+ return new HostedNativeSessionError(__privateGet(this, _code), __privateGet(this, _reason));
1308
1333
  }
1309
1334
  };
1310
1335
  _aborted = new WeakMap();
1311
1336
  _code = new WeakMap();
1337
+ _reason = new WeakMap();
1312
1338
  _listeners = new WeakMap();
1313
1339
  function raceWithAbort(promise, controller) {
1314
1340
  if (controller.signal.aborted) return Promise.reject(controller.error());
@@ -1616,7 +1642,7 @@ function createNativeAdmissionOwner(options) {
1616
1642
  reported = code;
1617
1643
  if (state.status !== "error") return;
1618
1644
  try {
1619
- input.onSessionError?.(Object.freeze({ code: state.error.code, kind: state.error.kind }));
1645
+ input.onSessionError?.(Object.freeze({ ...state.error }));
1620
1646
  } catch {
1621
1647
  }
1622
1648
  });
@@ -1,4 +1,4 @@
1
- import { B as MapThemeSelection, g as MapColorScheme } from '../contract-BaK24QZD.js';
1
+ import { B as MapThemeSelection, g as MapColorScheme } from '../contract-BWCbfMOx.js';
2
2
  import '@maplibre/maplibre-react-native';
3
3
  import 'react';
4
4
  import 'react-native';
@@ -47,7 +47,9 @@ type HostedNativeSessionErrorKind = 'terminal' | 'recoverable' | 'cancelled';
47
47
  declare class HostedNativeSessionError extends Error {
48
48
  readonly code: HostedNativeSessionErrorCode;
49
49
  readonly kind: HostedNativeSessionErrorKind;
50
- constructor(code: HostedNativeSessionErrorCode);
50
+ /** For `NATIVE_SESSION_REJECTED`, the service's code when its answer carried one. */
51
+ readonly reason?: string;
52
+ constructor(code: HostedNativeSessionErrorCode, reason?: string);
51
53
  }
52
54
  type HostedNativeSessionAuthority = Readonly<{
53
55
  grant: string;
@@ -71,6 +73,7 @@ type HostedNativeResourcePolicy = Readonly<Pick<HostedNativeSessionAuthority, 'm
71
73
  type SafeError = Readonly<{
72
74
  code: HostedNativeSessionErrorCode;
73
75
  kind: HostedNativeSessionErrorKind;
76
+ reason?: string;
74
77
  }>;
75
78
  type Lifecycle = 'foreground' | 'background';
76
79
  type HostedNativeSessionState = Readonly<{
@@ -24,6 +24,8 @@ var RETRY_LIMIT_MS = 6e4;
24
24
  var RETRY_AFTER_LIMIT_MS = 15 * 60 * 1e3;
25
25
  var RETRY_AFTER_SECONDS = /^\d{1,10}$/u;
26
26
  var QUOTA_CODES = /* @__PURE__ */ new Set(["COMMERCIAL_MAP_LIMIT_REACHED", "COMMERCIAL_SPENDING_LIMIT_REACHED"]);
27
+ var SERVICE_CODE = /^[A-Z][A-Z0-9_]{0,63}$/u;
28
+ var SERVICE_CODE_BODY_LIMIT = 4096;
27
29
  var MOBILE_CREDENTIAL = /^tf_public_[0-9a-f]{48}$/u;
28
30
  var MAP_ID = /^map_[A-Za-z0-9_-]{16}$/u;
29
31
  var CREDENTIAL_ID = /^key_[A-Za-z0-9_-]{8,80}$/u;
@@ -67,7 +69,8 @@ var TERMINAL_CODES = /* @__PURE__ */ new Set([
67
69
  "NATIVE_SESSION_CREDENTIAL_REJECTED",
68
70
  "NATIVE_SESSION_MAP_MISMATCH",
69
71
  "NATIVE_SESSION_MAP_NOT_FOUND",
70
- "NATIVE_SESSION_QUOTA_EXCEEDED"
72
+ "NATIVE_SESSION_QUOTA_EXCEEDED",
73
+ "NATIVE_SESSION_REJECTED"
71
74
  ]);
72
75
  var ERROR_MESSAGES = {
73
76
  NATIVE_SESSION_INPUT_INVALID: "Native session configuration is invalid.",
@@ -86,13 +89,16 @@ var ERROR_MESSAGES = {
86
89
  NATIVE_SESSION_DISPOSED: "Native session controller is disposed."
87
90
  };
88
91
  var HostedNativeSessionError = class extends Error {
89
- constructor(code) {
92
+ constructor(code, reason) {
90
93
  super(ERROR_MESSAGES[code]);
91
94
  __publicField(this, "code");
92
95
  __publicField(this, "kind");
93
96
  this.name = "HostedNativeSessionError";
94
97
  this.code = code;
95
98
  this.kind = errorKind(code);
99
+ if (code === "NATIVE_SESSION_REJECTED" && typeof reason === "string" && SERVICE_CODE.test(reason)) {
100
+ this.reason = reason;
101
+ }
96
102
  }
97
103
  };
98
104
  function createHostedNativeSessionController(input) {
@@ -221,10 +227,10 @@ function createHostedNativeSessionController(input) {
221
227
  if (retryAt === null || at >= retryAt) failures = Math.min(failures + 1, 16);
222
228
  const backoff = Math.min(RETRY_INITIAL_MS * 2 ** (failures - 1), RETRY_LIMIT_MS);
223
229
  retryAt = Math.max(retryAt ?? at, at + Math.max(backoff, retryAfterDelays.get(error) ?? 0));
224
- retryError = Object.freeze({ code: error.code, kind: error.kind });
230
+ retryError = safeError(error);
225
231
  }
226
232
  function rotateIfRequired(at) {
227
- if (terminal) throw new HostedNativeSessionError(terminal.code);
233
+ if (terminal) throw errorFrom(terminal);
228
234
  if (!activeSession || binding.kind !== "hosted") return;
229
235
  if (at - activeSession.startedAt < ROTATION_AGE_MS && activeSession.requestCount < ROTATION_REQUEST_LIMIT) {
230
236
  return;
@@ -258,7 +264,7 @@ function createHostedNativeSessionController(input) {
258
264
  return current;
259
265
  }
260
266
  async function ensureAuthority(session, at) {
261
- if (terminal) throw new HostedNativeSessionError(terminal.code);
267
+ if (terminal) throw errorFrom(terminal);
262
268
  if (session.authority && session.authority.clockEpoch === clock.epoch && session.authority.validUntil - at > REFRESH_MARGIN_MS) {
263
269
  return { authority: session.authority, session };
264
270
  }
@@ -270,7 +276,7 @@ function createHostedNativeSessionController(input) {
270
276
  if (session.authority && session.authority.clockEpoch === clock.epoch && session.authority.validUntil > at) {
271
277
  return { authority: session.authority, session };
272
278
  }
273
- throw new HostedNativeSessionError(retryError.code);
279
+ throw errorFrom(retryError);
274
280
  }
275
281
  const operationBinding = binding;
276
282
  const abort = new SessionAbortController();
@@ -297,14 +303,16 @@ function createHostedNativeSessionController(input) {
297
303
  const normalized = abort.signal.aborted ? abort.error() : normalizeError(error);
298
304
  const target = latestSession(session);
299
305
  if (normalized.kind === "terminal" && binding === operationBinding && !terminal) {
300
- const failure = Object.freeze({ code: normalized.code, kind: normalized.kind });
306
+ const failure = safeError(normalized);
301
307
  terminal = failure;
302
308
  const rejectedSession = activeSession;
303
309
  if (rejectedSession) {
304
310
  rejectedSession.authority = null;
305
311
  rejectedSession.error = failure;
306
312
  }
307
- for (const pending of [...operations]) pending.abort(failure.code);
313
+ for (const pending of [...operations]) {
314
+ pending.abort(failure.code, failure.reason);
315
+ }
308
316
  if (binding === operationBinding && rejectedSession) {
309
317
  publishSession(rejectedSession, "error", failure);
310
318
  }
@@ -313,7 +321,7 @@ function createHostedNativeSessionController(input) {
313
321
  delayRetry(normalized);
314
322
  }
315
323
  if (normalized.code !== "NATIVE_SESSION_REPLACED" && normalized.code !== "NATIVE_SESSION_DISPOSED") {
316
- target.error = Object.freeze({ code: normalized.code, kind: normalized.kind });
324
+ target.error = safeError(normalized);
317
325
  publishSession(target, "error", target.error);
318
326
  }
319
327
  throw normalized;
@@ -339,7 +347,7 @@ function createHostedNativeSessionController(input) {
339
347
  if (abort.signal.aborted) throw abort.error();
340
348
  const expectedSurfaceId = session.authority?.public.surfaceId ?? session.requestedSurfaceId;
341
349
  const response = await fetchResponse(hostedBinding, session, expectedSurfaceId, abort);
342
- const source = await readBoundedResponse(response, abort);
350
+ const { source, size } = await readBoundedResponse(response, abort);
343
351
  let body;
344
352
  try {
345
353
  body = source.length ? JSON.parse(source) : null;
@@ -349,14 +357,15 @@ function createHostedNativeSessionController(input) {
349
357
  }
350
358
  body = null;
351
359
  }
352
- if (response.status === 409 && allowRestart && isExactRestart(body, session.sessionId)) {
360
+ if (response.status === 409 && isExactRestart(body, session.sessionId)) {
361
+ if (!allowRestart) throw new HostedNativeSessionError("NATIVE_SESSION_UNAVAILABLE");
353
362
  assertCurrentSession(session, hostedBinding);
354
363
  const replacement = redirectSession(session, readClock());
355
364
  if (abort.signal.aborted) throw abort.error();
356
365
  return bootstrap(replacement, hostedBinding, abort, false, false);
357
366
  }
358
367
  if (response.status !== 201) {
359
- const failure = statusError(response.status, body);
368
+ const failure = statusError(response.status, body, size);
360
369
  const delay = retryAfterMs(response.headers, now);
361
370
  if (delay !== null) retryAfterDelays.set(failure, delay);
362
371
  throw failure;
@@ -494,7 +503,7 @@ function createHostedNativeSessionController(input) {
494
503
  if (bindingGeneration !== expectedGeneration) {
495
504
  throw new HostedNativeSessionError("NATIVE_SESSION_REPLACED");
496
505
  }
497
- if (terminal) throw new HostedNativeSessionError(terminal.code);
506
+ if (terminal) throw errorFrom(terminal);
498
507
  checkedAt = readClock();
499
508
  if (resolved.authority.clockEpoch === clock.epoch && resolved.authority.validUntil > checkedAt) {
500
509
  admittedAuthorities.set(resolved.authority.public, resolved.authority);
@@ -569,7 +578,7 @@ function createHostedNativeSessionController(input) {
569
578
  if (disposed) throw new HostedNativeSessionError("NATIVE_SESSION_DISPOSED");
570
579
  lifecycle = "foreground";
571
580
  if (terminal) {
572
- const error = new HostedNativeSessionError(terminal.code);
581
+ const error = errorFrom(terminal);
573
582
  publish(currentSnapshot());
574
583
  throw error;
575
584
  }
@@ -842,7 +851,7 @@ async function readBoundedResponse(response, abort) {
842
851
  bytes.set(chunk, offset);
843
852
  offset += chunk.byteLength;
844
853
  }
845
- return decodeUtf8(bytes);
854
+ return { source: decodeUtf8(bytes), size };
846
855
  }
847
856
  function decodeUtf8(bytes) {
848
857
  let result = "";
@@ -890,7 +899,7 @@ function decodeUtf8(bytes) {
890
899
  function hasNoStore(value) {
891
900
  return typeof value === "string" && value.split(",").some((part) => part.trim().toLowerCase() === "no-store");
892
901
  }
893
- function statusError(status, body) {
902
+ function statusError(status, body, size) {
894
903
  if (status === 401) return new HostedNativeSessionError("NATIVE_SESSION_CREDENTIAL_REJECTED");
895
904
  if (status === 403) return new HostedNativeSessionError("NATIVE_SESSION_MAP_MISMATCH");
896
905
  if (status === 404) return new HostedNativeSessionError("NATIVE_SESSION_MAP_NOT_FOUND");
@@ -902,7 +911,21 @@ function statusError(status, body) {
902
911
  if (status === 408 || status >= 500 && status <= 599) {
903
912
  return new HostedNativeSessionError("NATIVE_SESSION_UNAVAILABLE");
904
913
  }
905
- return new HostedNativeSessionError("NATIVE_SESSION_REJECTED");
914
+ if (status >= 400 && status <= 499) {
915
+ return new HostedNativeSessionError(
916
+ "NATIVE_SESSION_REJECTED",
917
+ size <= SERVICE_CODE_BODY_LIMIT && isRecord(body) && typeof body.code === "string" ? body.code : void 0
918
+ );
919
+ }
920
+ return new HostedNativeSessionError("NATIVE_SESSION_RESPONSE_INVALID");
921
+ }
922
+ function safeError(error) {
923
+ return Object.freeze(
924
+ error.reason === void 0 ? { code: error.code, kind: error.kind } : { code: error.code, kind: error.kind, reason: error.reason }
925
+ );
926
+ }
927
+ function errorFrom(error) {
928
+ return new HostedNativeSessionError(error.code, error.reason);
906
929
  }
907
930
  var retryAfterDelays = /* @__PURE__ */ new WeakMap();
908
931
  function retryAfterMs(headers, now) {
@@ -952,12 +975,13 @@ async function cancelResponse(response) {
952
975
  } catch {
953
976
  }
954
977
  }
955
- var _aborted, _code, _listeners;
978
+ var _aborted, _code, _reason, _listeners;
956
979
  var SessionAbortController = class {
957
980
  constructor() {
958
981
  __publicField(this, "signal");
959
982
  __privateAdd(this, _aborted, false);
960
983
  __privateAdd(this, _code, "NATIVE_SESSION_REPLACED");
984
+ __privateAdd(this, _reason);
961
985
  __privateAdd(this, _listeners, /* @__PURE__ */ new Set());
962
986
  const isAborted = () => __privateGet(this, _aborted);
963
987
  this.signal = Object.freeze({
@@ -972,9 +996,10 @@ var SessionAbortController = class {
972
996
  }
973
997
  });
974
998
  }
975
- abort(code) {
999
+ abort(code, reason) {
976
1000
  if (__privateGet(this, _aborted)) return;
977
1001
  __privateSet(this, _code, code);
1002
+ __privateSet(this, _reason, reason);
978
1003
  __privateSet(this, _aborted, true);
979
1004
  for (const listener of [...__privateGet(this, _listeners)]) {
980
1005
  try {
@@ -985,11 +1010,12 @@ var SessionAbortController = class {
985
1010
  __privateGet(this, _listeners).clear();
986
1011
  }
987
1012
  error() {
988
- return new HostedNativeSessionError(__privateGet(this, _code));
1013
+ return new HostedNativeSessionError(__privateGet(this, _code), __privateGet(this, _reason));
989
1014
  }
990
1015
  };
991
1016
  _aborted = new WeakMap();
992
1017
  _code = new WeakMap();
1018
+ _reason = new WeakMap();
993
1019
  _listeners = new WeakMap();
994
1020
  function raceWithAbort(promise, controller) {
995
1021
  if (controller.signal.aborted) return Promise.reject(controller.error());
@@ -1,5 +1,5 @@
1
1
  import { TileflowNativeSourceState } from '@tileflow/core/native';
2
- import { x as MapSourceState } from '../contract-BaK24QZD.js';
2
+ import { x as MapSourceState } from '../contract-BWCbfMOx.js';
3
3
  import '@maplibre/maplibre-react-native';
4
4
  import 'react';
5
5
  import 'react-native';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/react-native",
3
- "version": "0.1.0-alpha.7",
3
+ "version": "0.1.0-alpha.9",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Tileflow maps, camera control and semantic interactions for React Native.",
6
6
  "type": "module",
@@ -18,7 +18,6 @@
18
18
  "types": "./dist/index.d.ts",
19
19
  "files": [
20
20
  "dist",
21
- "docs",
22
21
  "android/build.gradle",
23
22
  "android/src/main",
24
23
  "ios/*.h",
@@ -36,8 +35,8 @@
36
35
  }
37
36
  },
38
37
  "dependencies": {
39
- "@tileflow/core": ">=0.1.0-alpha.42 <0.1.0-beta.0",
40
- "@tileflow/interactions": ">=0.1.0-alpha.6 <0.1.0-beta.0"
38
+ "@tileflow/core": ">=0.1.0-alpha.48 <0.1.0-beta.0",
39
+ "@tileflow/interactions": ">=0.1.0-alpha.8 <0.1.0-beta.0"
41
40
  },
42
41
  "peerDependencies": {
43
42
  "@maplibre/maplibre-react-native": "11.5.0",