@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.
- package/README.md +19 -17
- package/dist/{contract-BaK24QZD.d.ts → contract-BWCbfMOx.d.ts} +19 -7
- package/dist/index.d.ts +2 -2
- package/dist/index.js +444 -75
- package/dist/internal/camera.d.ts +1 -1
- package/dist/internal/initial-view.d.ts +1 -1
- package/dist/internal/interactions.js +1 -0
- package/dist/internal/native-admission.d.ts +1 -0
- package/dist/internal/native-admission.js +47 -21
- package/dist/internal/native-appearance.d.ts +1 -1
- package/dist/internal/session.d.ts +4 -1
- package/dist/internal/session.js +46 -20
- package/dist/internal/source-state.d.ts +1 -1
- package/package.json +3 -4
- package/docs/native-admission.md +0 -124
- package/docs/native-configuration.md +0 -210
- package/docs/native-interactions.md +0 -161
- package/docs/native-location.md +0 -148
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as MapView, a as MapViewChangeEvent, b as MapInitialViewInputs, c as MapCameraProps } from '../contract-
|
|
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';
|
|
@@ -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 =
|
|
549
|
+
retryError = safeError(error);
|
|
544
550
|
}
|
|
545
551
|
function rotateIfRequired(at) {
|
|
546
|
-
if (terminal) throw
|
|
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
|
|
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
|
|
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 =
|
|
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])
|
|
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 =
|
|
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 &&
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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({
|
|
1645
|
+
input.onSessionError?.(Object.freeze({ ...state.error }));
|
|
1620
1646
|
} catch {
|
|
1621
1647
|
}
|
|
1622
1648
|
});
|
|
@@ -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
|
-
|
|
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<{
|
package/dist/internal/session.js
CHANGED
|
@@ -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 =
|
|
230
|
+
retryError = safeError(error);
|
|
225
231
|
}
|
|
226
232
|
function rotateIfRequired(at) {
|
|
227
|
-
if (terminal) throw
|
|
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
|
|
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
|
|
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 =
|
|
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])
|
|
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 =
|
|
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 &&
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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-
|
|
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.
|
|
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.
|
|
40
|
-
"@tileflow/interactions": ">=0.1.0-alpha.
|
|
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",
|