@tileflow/react-native 0.1.0-alpha.5 → 0.1.0-alpha.7

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-Bp-Im7tj.js';
1
+ import { M as MapView, a as MapViewChangeEvent, b as MapInitialViewInputs, c as MapCameraProps } from '../contract-BaK24QZD.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-Bp-Im7tj.js';
1
+ import { b as MapInitialViewInputs, M as MapView } from '../contract-BaK24QZD.js';
2
2
  import '@maplibre/maplibre-react-native';
3
3
  import 'react';
4
4
  import 'react-native';
@@ -44,7 +44,9 @@ var nativeBootstrapLimits = Object.freeze({
44
44
  queueDepth: 32,
45
45
  requestBytes: 2048,
46
46
  responseBytes: 65536,
47
- timeoutMs: 3e4
47
+ retryAfterCharacters: 64,
48
+ // Well inside the 30 s ticket and batch deadlines.
49
+ timeoutMs: 1e4
48
50
  });
49
51
 
50
52
  // src/native-admission-wire.ts
@@ -75,10 +77,11 @@ function decodeBoundedBase64(value) {
75
77
  return bytes;
76
78
  }
77
79
  function responseFromWire(reply, isAborted, release) {
78
- if (!reply || !Number.isInteger(reply.status) || reply.status < 100 || reply.status > 599 || typeof reply.cacheControl !== "string" || reply.cacheControl.length > 1024)
80
+ if (!reply || !Number.isInteger(reply.status) || reply.status < 100 || reply.status > 599 || typeof reply.cacheControl !== "string" || reply.cacheControl.length > 1024 || reply.retryAfter !== void 0 && (typeof reply.retryAfter !== "string" || reply.retryAfter.length > nativeBootstrapLimits.retryAfterCharacters))
79
81
  throw invalid();
80
82
  const status = reply.status;
81
83
  const cacheControl = reply.cacheControl;
84
+ const retryAfter = reply.retryAfter || null;
82
85
  let bytes = decodeBoundedBase64(reply.bodyBase64);
83
86
  let readerTaken = false;
84
87
  let done = false;
@@ -92,7 +95,9 @@ function responseFromWire(reply, isAborted, release) {
92
95
  status,
93
96
  headers: Object.freeze({
94
97
  get(name) {
95
- return name.toLowerCase() === "cache-control" ? cacheControl : null;
98
+ const header = name.toLowerCase();
99
+ if (header === "cache-control") return cacheControl;
100
+ return header === "retry-after" ? retryAfter : null;
96
101
  }
97
102
  }),
98
103
  body: Object.freeze({
@@ -1,5 +1,5 @@
1
1
  import { e as NativeAdmissionCode, a as NativeAdmissionResource, f as NativeAdmissionBridge, d as NativeRemovalAck } from '../native-admission-contract-DFLfUP9X.js';
2
- import { HostedNativeResourcePolicy, createHostedNativeSessionController, HostedNativeSessionFetch, HostedNativeSessionController } from './session.js';
2
+ import { HostedNativeResourcePolicy, createHostedNativeSessionController, HostedNativeSessionFetch, HostedNativeSessionErrorCode, HostedNativeSessionErrorKind, HostedNativeSessionController } from './session.js';
3
3
 
4
4
  type SessionInput = Parameters<typeof createHostedNativeSessionController>[0];
5
5
  type NativeMapAdmissionInput = Omit<SessionInput, 'fetch' | 'sessionIdFactory'> & Readonly<{
@@ -7,6 +7,11 @@ type NativeMapAdmissionInput = Omit<SessionInput, 'fetch' | 'sessionIdFactory'>
7
7
  sessionIdFactory?: () => string;
8
8
  resources: readonly NativeAdmissionResource[];
9
9
  onRetired?: () => void;
10
+ /** Each time the session enters an error, including after first preparation. */
11
+ onSessionError?: (error: Readonly<{
12
+ code: HostedNativeSessionErrorCode;
13
+ kind: HostedNativeSessionErrorKind;
14
+ }>) => void;
10
15
  }>;
11
16
  type NativeMapAdmission = Readonly<{
12
17
  context: string;
@@ -25,6 +30,10 @@ type NativeMapAdmission = Readonly<{
25
30
  extendResources(resources: readonly NativeAdmissionResource[]): Promise<Readonly<{
26
31
  resources: number;
27
32
  }>>;
33
+ /** Lets a stopped or delayed session bootstrap again on its next acquisition. */
34
+ retry(): void;
35
+ /** Milliseconds until the session may bootstrap after a recoverable failure, or null. */
36
+ retryDelay(): number | null;
28
37
  retire(): Promise<Readonly<{
29
38
  retired: true;
30
39
  }>>;
@@ -63,6 +72,10 @@ declare function createNativeAdmissionOwner(options: {
63
72
  extendResources(resources: readonly NativeAdmissionResource[]): Promise<Readonly<{
64
73
  resources: number;
65
74
  }>>;
75
+ /** Lets a stopped or delayed session bootstrap again on its next acquisition. */
76
+ retry(): void;
77
+ /** Milliseconds until the session may bootstrap after a recoverable failure, or null. */
78
+ retryDelay(): number | null;
66
79
  retire(): Promise<Readonly<{
67
80
  retired: true;
68
81
  }>>;
@@ -338,6 +338,11 @@ var REFRESH_MARGIN_MS = 3e4;
338
338
  var ROTATION_AGE_MS = 6 * 60 * 60 * 1e3;
339
339
  var ROTATION_REQUEST_LIMIT = 1e4;
340
340
  var FUTURE_ISSUE_SKEW_MS = 3e4;
341
+ var RETRY_INITIAL_MS = 1e3;
342
+ var RETRY_LIMIT_MS = 6e4;
343
+ var RETRY_AFTER_LIMIT_MS = 15 * 60 * 1e3;
344
+ var RETRY_AFTER_SECONDS = /^\d{1,10}$/u;
345
+ var QUOTA_CODES = /* @__PURE__ */ new Set(["COMMERCIAL_MAP_LIMIT_REACHED", "COMMERCIAL_SPENDING_LIMIT_REACHED"]);
341
346
  var MOBILE_CREDENTIAL = /^tf_public_[0-9a-f]{48}$/u;
342
347
  var MAP_ID = /^map_[A-Za-z0-9_-]{16}$/u;
343
348
  var CREDENTIAL_ID = /^key_[A-Za-z0-9_-]{8,80}$/u;
@@ -376,6 +381,13 @@ var SUCCESS_KEYS = /* @__PURE__ */ new Set([
376
381
  "tilesetIds"
377
382
  ]);
378
383
  var RESTART_KEYS = /* @__PURE__ */ new Set(["code", "error", "retryWithNewSession", "sessionId"]);
384
+ var TERMINAL_CODES = /* @__PURE__ */ new Set([
385
+ "NATIVE_SESSION_INPUT_INVALID",
386
+ "NATIVE_SESSION_CREDENTIAL_REJECTED",
387
+ "NATIVE_SESSION_MAP_MISMATCH",
388
+ "NATIVE_SESSION_MAP_NOT_FOUND",
389
+ "NATIVE_SESSION_QUOTA_EXCEEDED"
390
+ ]);
379
391
  var ERROR_MESSAGES = {
380
392
  NATIVE_SESSION_INPUT_INVALID: "Native session configuration is invalid.",
381
393
  NATIVE_SESSION_RESPONSE_TOO_LARGE: "Native session response exceeded its byte limit.",
@@ -387,6 +399,7 @@ var ERROR_MESSAGES = {
387
399
  NATIVE_SESSION_MAP_NOT_FOUND: "Native session Map was not found.",
388
400
  NATIVE_SESSION_QUOTA_EXCEEDED: "Native session quota was exceeded.",
389
401
  NATIVE_SESSION_REJECTED: "Native session request was rejected.",
402
+ NATIVE_SESSION_RATE_LIMITED: "Native session requests are rate limited.",
390
403
  NATIVE_SESSION_UNAVAILABLE: "Native session service is unavailable.",
391
404
  NATIVE_SESSION_REPLACED: "Native session binding was replaced.",
392
405
  NATIVE_SESSION_DISPOSED: "Native session controller is disposed."
@@ -508,7 +521,29 @@ function createHostedNativeSessionController(input) {
508
521
  })
509
522
  );
510
523
  }
524
+ let terminal = null;
525
+ let failures = 0;
526
+ let retryAt = null;
527
+ let retryError = null;
528
+ function clearRetry() {
529
+ failures = 0;
530
+ retryAt = null;
531
+ retryError = null;
532
+ }
533
+ function delayRetry(error) {
534
+ let at;
535
+ try {
536
+ at = readClock();
537
+ } catch {
538
+ return;
539
+ }
540
+ if (retryAt === null || at >= retryAt) failures = Math.min(failures + 1, 16);
541
+ const backoff = Math.min(RETRY_INITIAL_MS * 2 ** (failures - 1), RETRY_LIMIT_MS);
542
+ retryAt = Math.max(retryAt ?? at, at + Math.max(backoff, retryAfterDelays.get(error) ?? 0));
543
+ retryError = Object.freeze({ code: error.code, kind: error.kind });
544
+ }
511
545
  function rotateIfRequired(at) {
546
+ if (terminal) throw new HostedNativeSessionError(terminal.code);
512
547
  if (!activeSession || binding.kind !== "hosted") return;
513
548
  if (at - activeSession.startedAt < ROTATION_AGE_MS && activeSession.requestCount < ROTATION_REQUEST_LIMIT) {
514
549
  return;
@@ -542,6 +577,7 @@ function createHostedNativeSessionController(input) {
542
577
  return current;
543
578
  }
544
579
  async function ensureAuthority(session, at) {
580
+ if (terminal) throw new HostedNativeSessionError(terminal.code);
545
581
  if (session.authority && session.authority.clockEpoch === clock.epoch && session.authority.validUntil - at > REFRESH_MARGIN_MS) {
546
582
  return { authority: session.authority, session };
547
583
  }
@@ -549,20 +585,28 @@ function createHostedNativeSessionController(input) {
549
585
  if (binding.kind !== "hosted") {
550
586
  throw new HostedNativeSessionError("NATIVE_SESSION_REPLACED");
551
587
  }
588
+ if (retryAt !== null && retryError && at < retryAt) {
589
+ if (session.authority && session.authority.clockEpoch === clock.epoch && session.authority.validUntil > at) {
590
+ return { authority: session.authority, session };
591
+ }
592
+ throw new HostedNativeSessionError(retryError.code);
593
+ }
552
594
  const operationBinding = binding;
553
595
  const abort = new SessionAbortController();
554
596
  operations.add(abort);
555
597
  const operation = {
556
598
  abort,
557
599
  promise: Promise.resolve().then(async () => {
558
- session.error = null;
559
- publishSession(session, "loading");
560
- if (abort.signal.aborted) throw abort.error();
561
600
  try {
601
+ if (abort.signal.aborted) throw abort.error();
602
+ session.error = null;
603
+ publishSession(session, "loading");
604
+ if (abort.signal.aborted) throw abort.error();
562
605
  const result = await bootstrap(session, operationBinding, abort, true, true);
563
606
  if (abort.signal.aborted) throw abort.error();
564
607
  result.session.authority = result.authority;
565
608
  result.session.error = null;
609
+ if (binding === operationBinding) clearRetry();
566
610
  if (activeSession === result.session) {
567
611
  publishSession(result.session, "ready");
568
612
  if (abort.signal.aborted) throw abort.error();
@@ -571,6 +615,22 @@ function createHostedNativeSessionController(input) {
571
615
  } catch (error) {
572
616
  const normalized = abort.signal.aborted ? abort.error() : normalizeError(error);
573
617
  const target = latestSession(session);
618
+ if (normalized.kind === "terminal" && binding === operationBinding && !terminal) {
619
+ const failure = Object.freeze({ code: normalized.code, kind: normalized.kind });
620
+ terminal = failure;
621
+ const rejectedSession = activeSession;
622
+ if (rejectedSession) {
623
+ rejectedSession.authority = null;
624
+ rejectedSession.error = failure;
625
+ }
626
+ for (const pending of [...operations]) pending.abort(failure.code);
627
+ if (binding === operationBinding && rejectedSession) {
628
+ publishSession(rejectedSession, "error", failure);
629
+ }
630
+ }
631
+ if (normalized.kind === "recoverable" && binding === operationBinding && !terminal) {
632
+ delayRetry(normalized);
633
+ }
574
634
  if (normalized.code !== "NATIVE_SESSION_REPLACED" && normalized.code !== "NATIVE_SESSION_DISPOSED") {
575
635
  target.error = Object.freeze({ code: normalized.code, kind: normalized.kind });
576
636
  publishSession(target, "error", target.error);
@@ -603,7 +663,10 @@ function createHostedNativeSessionController(input) {
603
663
  try {
604
664
  body = source.length ? JSON.parse(source) : null;
605
665
  } catch {
606
- throw new HostedNativeSessionError("NATIVE_SESSION_RESPONSE_JSON_INVALID");
666
+ if (response.status === 201) {
667
+ throw new HostedNativeSessionError("NATIVE_SESSION_RESPONSE_JSON_INVALID");
668
+ }
669
+ body = null;
607
670
  }
608
671
  if (response.status === 409 && allowRestart && isExactRestart(body, session.sessionId)) {
609
672
  assertCurrentSession(session, hostedBinding);
@@ -611,7 +674,12 @@ function createHostedNativeSessionController(input) {
611
674
  if (abort.signal.aborted) throw abort.error();
612
675
  return bootstrap(replacement, hostedBinding, abort, false, false);
613
676
  }
614
- if (response.status !== 201) throw statusError(response.status);
677
+ if (response.status !== 201) {
678
+ const failure = statusError(response.status, body);
679
+ const delay = retryAfterMs(response.headers, now);
680
+ if (delay !== null) retryAfterDelays.set(failure, delay);
681
+ throw failure;
682
+ }
615
683
  if (!hasNoStore(response.headers.get("cache-control"))) {
616
684
  throw new HostedNativeSessionError("NATIVE_SESSION_RESPONSE_INVALID");
617
685
  }
@@ -684,6 +752,16 @@ function createHostedNativeSessionController(input) {
684
752
  if (binding.kind === "direct" || !activeSession) {
685
753
  return Object.freeze({ status: "idle", source: "direct", lifecycle });
686
754
  }
755
+ if (terminal) {
756
+ return Object.freeze({
757
+ status: "error",
758
+ source: "hosted",
759
+ lifecycle,
760
+ mapId: binding.mapId,
761
+ sessionId: activeSession.sessionId,
762
+ error: terminal
763
+ });
764
+ }
687
765
  if (activeSession.operation) {
688
766
  return Object.freeze({
689
767
  status: "loading",
@@ -735,6 +813,7 @@ function createHostedNativeSessionController(input) {
735
813
  if (bindingGeneration !== expectedGeneration) {
736
814
  throw new HostedNativeSessionError("NATIVE_SESSION_REPLACED");
737
815
  }
816
+ if (terminal) throw new HostedNativeSessionError(terminal.code);
738
817
  checkedAt = readClock();
739
818
  if (resolved.authority.clockEpoch === clock.epoch && resolved.authority.validUntil > checkedAt) {
740
819
  admittedAuthorities.set(resolved.authority.public, resolved.authority);
@@ -789,7 +868,7 @@ function createHostedNativeSessionController(input) {
789
868
  }
790
869
  },
791
870
  transportBudget(authority) {
792
- if (disposed || lifecycle !== "foreground") return 0;
871
+ if (disposed || terminal || lifecycle !== "foreground") return 0;
793
872
  const stored = admittedAuthorities.get(authority);
794
873
  if (!stored || stored.bindingGeneration !== bindingGeneration) return 0;
795
874
  try {
@@ -808,6 +887,11 @@ function createHostedNativeSessionController(input) {
808
887
  async resume() {
809
888
  if (disposed) throw new HostedNativeSessionError("NATIVE_SESSION_DISPOSED");
810
889
  lifecycle = "foreground";
890
+ if (terminal) {
891
+ const error = new HostedNativeSessionError(terminal.code);
892
+ publish(currentSnapshot());
893
+ throw error;
894
+ }
811
895
  if (binding.kind === "direct" || !activeSession) {
812
896
  publish(currentSnapshot());
813
897
  return;
@@ -830,9 +914,27 @@ function createHostedNativeSessionController(input) {
830
914
  bindingGeneration += 1;
831
915
  for (const operation of operations) operation.abort("NATIVE_SESSION_REPLACED");
832
916
  binding = next;
917
+ terminal = null;
918
+ clearRetry();
833
919
  activeSession = next.kind === "hosted" ? createSession(next.surfaceId, readClock()) : null;
834
920
  publish(snapshotIdle(binding, activeSession, lifecycle));
835
921
  },
922
+ retry() {
923
+ if (disposed) throw new HostedNativeSessionError("NATIVE_SESSION_DISPOSED");
924
+ if (!terminal && retryAt === null) return;
925
+ terminal = null;
926
+ clearRetry();
927
+ if (activeSession && !activeSession.operation) activeSession.error = null;
928
+ publish(currentSnapshot());
929
+ },
930
+ retryDelay() {
931
+ if (disposed || terminal || retryAt === null) return null;
932
+ try {
933
+ return Math.max(0, Math.ceil(retryAt - readClock()));
934
+ } catch {
935
+ return null;
936
+ }
937
+ },
836
938
  subscribe(listener) {
837
939
  if (typeof listener !== "function") {
838
940
  throw new HostedNativeSessionError("NATIVE_SESSION_INPUT_INVALID");
@@ -927,7 +1029,8 @@ function parseSuccess(value, binding, expectedSessionId, expectedSurfaceId) {
927
1029
  const issuedAtMs = parseExactIso(value.issuedAt);
928
1030
  const serverTimeMs = parseExactIso(value.serverTime);
929
1031
  const expiresAtMs = parseExactIso(value.expiresAt);
930
- if (issuedAtMs > serverTimeMs + FUTURE_ISSUE_SKEW_MS || expiresAtMs <= serverTimeMs || expiresAtMs <= issuedAtMs || expiresAtMs - issuedAtMs > MAX_GRANT_LIFETIME_MS || expiresAtMs - issuedAtMs > MAX_GRANT_LIFETIME_MS) {
1032
+ if (issuedAtMs > serverTimeMs + FUTURE_ISSUE_SKEW_MS || expiresAtMs <= serverTimeMs || expiresAtMs <= issuedAtMs || expiresAtMs - issuedAtMs > MAX_GRANT_LIFETIME_MS || // The local deadline is derived from serverTime, so this also bounds the transport budget.
1033
+ expiresAtMs - serverTimeMs > MAX_GRANT_LIFETIME_MS) {
931
1034
  throw new HostedNativeSessionError("NATIVE_SESSION_RESPONSE_INVALID");
932
1035
  }
933
1036
  const authority = {
@@ -1106,18 +1209,46 @@ function decodeUtf8(bytes) {
1106
1209
  function hasNoStore(value) {
1107
1210
  return typeof value === "string" && value.split(",").some((part) => part.trim().toLowerCase() === "no-store");
1108
1211
  }
1109
- function statusError(status) {
1212
+ function statusError(status, body) {
1110
1213
  if (status === 401) return new HostedNativeSessionError("NATIVE_SESSION_CREDENTIAL_REJECTED");
1111
1214
  if (status === 403) return new HostedNativeSessionError("NATIVE_SESSION_MAP_MISMATCH");
1112
1215
  if (status === 404) return new HostedNativeSessionError("NATIVE_SESSION_MAP_NOT_FOUND");
1113
- if (status === 429) return new HostedNativeSessionError("NATIVE_SESSION_QUOTA_EXCEEDED");
1114
- if (status === 503) return new HostedNativeSessionError("NATIVE_SESSION_UNAVAILABLE");
1216
+ if (status === 429) {
1217
+ return new HostedNativeSessionError(
1218
+ isRecord(body) && typeof body.code === "string" && QUOTA_CODES.has(body.code) ? "NATIVE_SESSION_QUOTA_EXCEEDED" : "NATIVE_SESSION_RATE_LIMITED"
1219
+ );
1220
+ }
1221
+ if (status === 408 || status >= 500 && status <= 599) {
1222
+ return new HostedNativeSessionError("NATIVE_SESSION_UNAVAILABLE");
1223
+ }
1115
1224
  return new HostedNativeSessionError("NATIVE_SESSION_REJECTED");
1116
1225
  }
1226
+ var retryAfterDelays = /* @__PURE__ */ new WeakMap();
1227
+ function retryAfterMs(headers, now) {
1228
+ let value;
1229
+ try {
1230
+ value = headers.get("retry-after");
1231
+ } catch {
1232
+ return null;
1233
+ }
1234
+ if (typeof value !== "string" || value.length > 64) return null;
1235
+ const text = value.trim();
1236
+ let delay;
1237
+ if (RETRY_AFTER_SECONDS.test(text)) delay = Number(text) * 1e3;
1238
+ else {
1239
+ const date = Date.parse(text);
1240
+ if (!Number.isFinite(date)) return null;
1241
+ try {
1242
+ delay = date - readWallClock(now);
1243
+ } catch {
1244
+ return null;
1245
+ }
1246
+ }
1247
+ return Math.min(Math.max(0, delay), RETRY_AFTER_LIMIT_MS);
1248
+ }
1117
1249
  function errorKind(code) {
1118
1250
  if (code === "NATIVE_SESSION_DISPOSED" || code === "NATIVE_SESSION_REPLACED") return "cancelled";
1119
- if (code === "NATIVE_SESSION_UNAVAILABLE") return "recoverable";
1120
- return "terminal";
1251
+ return TERMINAL_CODES.has(code) ? "terminal" : "recoverable";
1121
1252
  }
1122
1253
  function normalizeError(error, fallback = "NATIVE_SESSION_RESPONSE_INVALID") {
1123
1254
  return error instanceof HostedNativeSessionError ? error : new HostedNativeSessionError(fallback);
@@ -1416,6 +1547,8 @@ function createNativeAdmissionOwner(options) {
1416
1547
  try {
1417
1548
  resources = normalizeNativeResources(input.resources);
1418
1549
  if (input.onRetired !== void 0 && typeof input.onRetired !== "function") throw cancel();
1550
+ if (input.onSessionError !== void 0 && typeof input.onSessionError !== "function")
1551
+ throw cancel();
1419
1552
  } catch {
1420
1553
  throw cancel("NATIVE_ADMISSION_INVALID");
1421
1554
  }
@@ -1476,6 +1609,17 @@ function createNativeAdmissionOwner(options) {
1476
1609
  controller,
1477
1610
  handle: void 0
1478
1611
  };
1612
+ let reported = null;
1613
+ const releaseSession = controller.subscribe((state) => {
1614
+ const code = state.status === "error" ? state.error.code : null;
1615
+ if (!context.live || code === reported) return;
1616
+ reported = code;
1617
+ if (state.status !== "error") return;
1618
+ try {
1619
+ input.onSessionError?.(Object.freeze({ code: state.error.code, kind: state.error.kind }));
1620
+ } catch {
1621
+ }
1622
+ });
1479
1623
  context.handle = Object.freeze({
1480
1624
  context: context.id,
1481
1625
  generation: context.generation,
@@ -1505,9 +1649,26 @@ function createNativeAdmissionOwner(options) {
1505
1649
  discriminate: catalog.discriminate,
1506
1650
  discriminateForTest: catalog.discriminate,
1507
1651
  extendResources: catalog.extend,
1652
+ retry() {
1653
+ if (!context.live || disposed) return;
1654
+ try {
1655
+ controller.retry?.();
1656
+ } catch {
1657
+ }
1658
+ },
1659
+ retryDelay() {
1660
+ if (!context.live || disposed) return null;
1661
+ try {
1662
+ const delay = controller.retryDelay?.() ?? null;
1663
+ return delay !== null && Number.isSafeInteger(delay) && delay >= 0 ? delay : null;
1664
+ } catch {
1665
+ return null;
1666
+ }
1667
+ },
1508
1668
  retire() {
1509
1669
  if (retirement) return retirement;
1510
1670
  context.live = false;
1671
+ releaseSession();
1511
1672
  context.batch = null;
1512
1673
  context.tickets.clear();
1513
1674
  catalog.retire();
@@ -1,4 +1,4 @@
1
- import { z as MapThemeSelection, f as MapColorScheme } from '../contract-Bp-Im7tj.js';
1
+ import { B as MapThemeSelection, g as MapColorScheme } from '../contract-BaK24QZD.js';
2
2
  import '@maplibre/maplibre-react-native';
3
3
  import 'react';
4
4
  import 'react-native';
@@ -42,7 +42,7 @@ type HostedNativeSessionFetchResponse = Readonly<{
42
42
  }> | null;
43
43
  }>;
44
44
  type HostedNativeSessionFetch = (url: string, init: HostedNativeSessionFetchInit) => Promise<HostedNativeSessionFetchResponse>;
45
- type HostedNativeSessionErrorCode = 'NATIVE_SESSION_INPUT_INVALID' | 'NATIVE_SESSION_RESPONSE_TOO_LARGE' | 'NATIVE_SESSION_RESPONSE_UTF8_INVALID' | 'NATIVE_SESSION_RESPONSE_JSON_INVALID' | 'NATIVE_SESSION_RESPONSE_INVALID' | 'NATIVE_SESSION_CREDENTIAL_REJECTED' | 'NATIVE_SESSION_MAP_MISMATCH' | 'NATIVE_SESSION_MAP_NOT_FOUND' | 'NATIVE_SESSION_QUOTA_EXCEEDED' | 'NATIVE_SESSION_REJECTED' | 'NATIVE_SESSION_UNAVAILABLE' | 'NATIVE_SESSION_REPLACED' | 'NATIVE_SESSION_DISPOSED';
45
+ type HostedNativeSessionErrorCode = 'NATIVE_SESSION_INPUT_INVALID' | 'NATIVE_SESSION_RESPONSE_TOO_LARGE' | 'NATIVE_SESSION_RESPONSE_UTF8_INVALID' | 'NATIVE_SESSION_RESPONSE_JSON_INVALID' | 'NATIVE_SESSION_RESPONSE_INVALID' | 'NATIVE_SESSION_CREDENTIAL_REJECTED' | 'NATIVE_SESSION_MAP_MISMATCH' | 'NATIVE_SESSION_MAP_NOT_FOUND' | 'NATIVE_SESSION_QUOTA_EXCEEDED' | 'NATIVE_SESSION_REJECTED' | 'NATIVE_SESSION_RATE_LIMITED' | 'NATIVE_SESSION_UNAVAILABLE' | 'NATIVE_SESSION_REPLACED' | 'NATIVE_SESSION_DISPOSED';
46
46
  type HostedNativeSessionErrorKind = 'terminal' | 'recoverable' | 'cancelled';
47
47
  declare class HostedNativeSessionError extends Error {
48
48
  readonly code: HostedNativeSessionErrorCode;
@@ -112,6 +112,10 @@ type HostedNativeSessionController = Readonly<{
112
112
  background(): void;
113
113
  resume(): Promise<void>;
114
114
  replaceBinding(binding: HostedNativeSessionBinding): void;
115
+ /** Clears a terminal stop and any retry delay; the next acquisition bootstraps again. */
116
+ retry?(): void;
117
+ /** Milliseconds until a bootstrap may follow a recoverable failure, or null without one. */
118
+ retryDelay?(): number | null;
115
119
  subscribe(listener: (state: HostedNativeSessionState) => void): () => void;
116
120
  dispose(): void;
117
121
  }>;