@sendoracloud/sdk-react-native 1.35.0 → 1.36.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/dist/index.cjs +54 -5
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +54 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -65,6 +65,12 @@ async function getAsyncStorage() {
|
|
|
65
65
|
})();
|
|
66
66
|
return asyncStoragePromise;
|
|
67
67
|
}
|
|
68
|
+
var warned = /* @__PURE__ */ new Set();
|
|
69
|
+
function warnOnce(key, message) {
|
|
70
|
+
if (warned.has(key)) return;
|
|
71
|
+
warned.add(key);
|
|
72
|
+
console.warn(message);
|
|
73
|
+
}
|
|
68
74
|
var Storage = class {
|
|
69
75
|
constructor(opts = {}) {
|
|
70
76
|
this.cache = /* @__PURE__ */ new Map();
|
|
@@ -73,6 +79,12 @@ var Storage = class {
|
|
|
73
79
|
this.secureKeys = new Set(opts.secureKeys ?? []);
|
|
74
80
|
this.prefix = opts.prefix ?? DEFAULT_PREFIX;
|
|
75
81
|
this.securePrefix = opts.prefix ?? "";
|
|
82
|
+
if (this.secure === null && this.secureKeys.size > 0) {
|
|
83
|
+
warnOnce(
|
|
84
|
+
"no-secure-adapter",
|
|
85
|
+
"[sendora] No `secureStorage` adapter supplied \u2014 auth tokens (refresh token, access token, cached user) will be stored in PLAIN AsyncStorage, which is included in iOS/Android device backups. Pass `secureStorage` in init() with a Keychain/Keystore-backed adapter (e.g. expo-secure-store). The session still persists either way; this is about where the token rests."
|
|
86
|
+
);
|
|
87
|
+
}
|
|
76
88
|
}
|
|
77
89
|
/** The adapter-facing name for a key. Bare by default; see `prefix`. */
|
|
78
90
|
secureName(key) {
|
|
@@ -126,6 +138,10 @@ var Storage = class {
|
|
|
126
138
|
}
|
|
127
139
|
}
|
|
128
140
|
} catch {
|
|
141
|
+
warnOnce(
|
|
142
|
+
"secure-read-degraded",
|
|
143
|
+
"[sendora] The `secureStorage` adapter failed on read; falling back to plain AsyncStorage for this session. Tokens are preserved but no longer encrypted at rest. Check your adapter."
|
|
144
|
+
);
|
|
129
145
|
if (store) {
|
|
130
146
|
try {
|
|
131
147
|
const legacy = await store.getItem(this.prefix + k);
|
|
@@ -142,6 +158,10 @@ var Storage = class {
|
|
|
142
158
|
this.cache.set(key, value);
|
|
143
159
|
if (this.isSecure(key)) {
|
|
144
160
|
void this.secure.setItem(this.secureName(key), value).catch(() => {
|
|
161
|
+
warnOnce(
|
|
162
|
+
"secure-write-degraded",
|
|
163
|
+
"[sendora] The `secureStorage` adapter failed on write; this value fell back to plain AsyncStorage. The session is preserved but this token is no longer encrypted at rest. Check your adapter."
|
|
164
|
+
);
|
|
145
165
|
void getAsyncStorage().then((store) => {
|
|
146
166
|
if (store) store.setItem(this.prefix + key, value).catch(() => {
|
|
147
167
|
});
|
|
@@ -208,7 +228,7 @@ var Storage = class {
|
|
|
208
228
|
// package.json
|
|
209
229
|
var package_default = {
|
|
210
230
|
name: "@sendoracloud/sdk-react-native",
|
|
211
|
-
version: "1.
|
|
231
|
+
version: "1.36.0",
|
|
212
232
|
description: "Sendora Cloud React Native + Expo SDK \u2014 analytics, identity, push-token registration, auth (incl. Game Center / Play Games), deep links (Branch / Firebase Dynamic Links parity). Auth + analytics + deep links work in Expo Go; push-token registration and the no-arg Game Center / Play Games sign-in require a Dev Client (EAS Build or `npx expo prebuild`).",
|
|
213
233
|
type: "module",
|
|
214
234
|
main: "./dist/index.cjs",
|
|
@@ -496,6 +516,12 @@ function classifyAuthErrorKind(code, status) {
|
|
|
496
516
|
return "credential_in_use";
|
|
497
517
|
case "LAST_CREDENTIAL":
|
|
498
518
|
return "last_credential";
|
|
519
|
+
// ⚠ MUST be a code case, not a status one. The tail of this function is
|
|
520
|
+
// `if (status >= 400) return "invalid_credential"`, which would otherwise
|
|
521
|
+
// claim the 403 and report a step-up refusal as a bad credential —
|
|
522
|
+
// documented as "needs NEW input", which is the opposite of the truth.
|
|
523
|
+
case "RECENT_AUTH_REQUIRED":
|
|
524
|
+
return "recent_auth_required";
|
|
499
525
|
case "NOT_ANONYMOUS":
|
|
500
526
|
case "FORBIDDEN_NON_ANONYMOUS":
|
|
501
527
|
return "already_identified";
|
|
@@ -1582,13 +1608,24 @@ var Auth = class {
|
|
|
1582
1608
|
const data = await this.unwrap(res, "MFA_CONFIRM_FAILED");
|
|
1583
1609
|
return Boolean(data.confirmed);
|
|
1584
1610
|
}
|
|
1611
|
+
/**
|
|
1612
|
+
* Disable MFA.
|
|
1613
|
+
*
|
|
1614
|
+
* ⚠ STEP-UP gated (s58.319): a stale `auth_time` is refused with 403
|
|
1615
|
+
* `RECENT_AUTH_REQUIRED` / kind `recent_auth_required`.
|
|
1616
|
+
*
|
|
1617
|
+
* ⚠ Discarded its response until s58.335, and `request()` never throws on a
|
|
1618
|
+
* non-2xx (it warns and returns the Response), so the refusal had nowhere to
|
|
1619
|
+
* surface — the app reported MFA as off while TOTP stayed enrolled.
|
|
1620
|
+
*/
|
|
1585
1621
|
async disableMfa() {
|
|
1586
|
-
await post(
|
|
1622
|
+
const res = await post(
|
|
1587
1623
|
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
1588
1624
|
"/api/v1/auth-service/mfa/disable",
|
|
1589
1625
|
{},
|
|
1590
1626
|
this.bearerHeaders()
|
|
1591
1627
|
);
|
|
1628
|
+
await this.unwrap(res, "MFA_DISABLE_FAILED");
|
|
1592
1629
|
}
|
|
1593
1630
|
// ============================================================
|
|
1594
1631
|
// DEVICE SESSIONS (Bearer-authenticated)
|
|
@@ -1603,19 +1640,28 @@ var Auth = class {
|
|
|
1603
1640
|
const parsed = await res.json();
|
|
1604
1641
|
return Array.isArray(parsed.data) ? parsed.data : [];
|
|
1605
1642
|
}
|
|
1643
|
+
/**
|
|
1644
|
+
* Revoke one of the caller's own sessions ("sign out that device").
|
|
1645
|
+
* ⚠ Discarded its response until s58.335 — a "sign out this device" button
|
|
1646
|
+
* that reports success on a failure is the one place a user acts on the claim
|
|
1647
|
+
* and then stops worrying.
|
|
1648
|
+
*/
|
|
1606
1649
|
async revokeSession(sessionId) {
|
|
1607
|
-
await del(
|
|
1650
|
+
const res = await del(
|
|
1608
1651
|
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
1609
1652
|
`/api/v1/auth-service/sessions/me/${encodeURIComponent(sessionId)}`,
|
|
1610
1653
|
this.bearerHeaders()
|
|
1611
1654
|
);
|
|
1655
|
+
await this.unwrap(res, "SESSION_REVOKE_FAILED");
|
|
1612
1656
|
}
|
|
1657
|
+
/** Revoke every session for the caller. Same reporting defect as `revokeSession`. */
|
|
1613
1658
|
async revokeAllSessions() {
|
|
1614
|
-
await del(
|
|
1659
|
+
const res = await del(
|
|
1615
1660
|
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
1616
1661
|
"/api/v1/auth-service/sessions/me",
|
|
1617
1662
|
this.bearerHeaders()
|
|
1618
1663
|
);
|
|
1664
|
+
await this.unwrap(res, "SESSION_REVOKE_ALL_FAILED");
|
|
1619
1665
|
}
|
|
1620
1666
|
/**
|
|
1621
1667
|
* Delete the signed-in user's account (Apple App Store Guideline 5.1.1(v)).
|
|
@@ -1781,7 +1827,10 @@ var Auth = class {
|
|
|
1781
1827
|
if (!res) throw new AuthError("NETWORK_ERROR", "Network request failed");
|
|
1782
1828
|
const parsed = await res.json().catch(() => ({}));
|
|
1783
1829
|
if (!res.ok || !parsed.success) {
|
|
1784
|
-
throw new AuthError(parsed.error?.code ?? errCode, parsed.error?.message ?? `HTTP ${res.status}
|
|
1830
|
+
throw new AuthError(parsed.error?.code ?? errCode, parsed.error?.message ?? `HTTP ${res.status}`, {
|
|
1831
|
+
status: res.status,
|
|
1832
|
+
retryAfterSeconds: readRetryAfterSeconds(parsed)
|
|
1833
|
+
});
|
|
1785
1834
|
}
|
|
1786
1835
|
return parsed.data;
|
|
1787
1836
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -464,7 +464,7 @@ type UnlinkResult = {
|
|
|
464
464
|
* OTP, a dismissed Game Center sheet and a 429 all leave `getUserSync()` and
|
|
465
465
|
* the stored refresh token exactly as they were.
|
|
466
466
|
*/
|
|
467
|
-
type AuthErrorKind = "network" | "server" | "rate_limited" | "invalid_credential" | "account_locked" | "credential_in_use" | "last_credential" | "already_identified" | "cancelled" | "config" | "unknown";
|
|
467
|
+
type AuthErrorKind = "network" | "server" | "rate_limited" | "invalid_credential" | "account_locked" | "credential_in_use" | "last_credential" | "recent_auth_required" | "already_identified" | "cancelled" | "config" | "unknown";
|
|
468
468
|
declare class AuthError extends Error {
|
|
469
469
|
code: string;
|
|
470
470
|
/**
|
|
@@ -1109,6 +1109,16 @@ declare class Auth {
|
|
|
1109
1109
|
recoveryCodes: string[];
|
|
1110
1110
|
}>;
|
|
1111
1111
|
confirmMfa(code: string): Promise<boolean>;
|
|
1112
|
+
/**
|
|
1113
|
+
* Disable MFA.
|
|
1114
|
+
*
|
|
1115
|
+
* ⚠ STEP-UP gated (s58.319): a stale `auth_time` is refused with 403
|
|
1116
|
+
* `RECENT_AUTH_REQUIRED` / kind `recent_auth_required`.
|
|
1117
|
+
*
|
|
1118
|
+
* ⚠ Discarded its response until s58.335, and `request()` never throws on a
|
|
1119
|
+
* non-2xx (it warns and returns the Response), so the refusal had nowhere to
|
|
1120
|
+
* surface — the app reported MFA as off while TOTP stayed enrolled.
|
|
1121
|
+
*/
|
|
1112
1122
|
disableMfa(): Promise<void>;
|
|
1113
1123
|
listMySessions(): Promise<Array<{
|
|
1114
1124
|
id: string;
|
|
@@ -1117,7 +1127,14 @@ declare class Auth {
|
|
|
1117
1127
|
lastUsedAt: string | null;
|
|
1118
1128
|
createdAt: string;
|
|
1119
1129
|
}>>;
|
|
1130
|
+
/**
|
|
1131
|
+
* Revoke one of the caller's own sessions ("sign out that device").
|
|
1132
|
+
* ⚠ Discarded its response until s58.335 — a "sign out this device" button
|
|
1133
|
+
* that reports success on a failure is the one place a user acts on the claim
|
|
1134
|
+
* and then stops worrying.
|
|
1135
|
+
*/
|
|
1120
1136
|
revokeSession(sessionId: string): Promise<void>;
|
|
1137
|
+
/** Revoke every session for the caller. Same reporting defect as `revokeSession`. */
|
|
1121
1138
|
revokeAllSessions(): Promise<void>;
|
|
1122
1139
|
/**
|
|
1123
1140
|
* Delete the signed-in user's account (Apple App Store Guideline 5.1.1(v)).
|
package/dist/index.d.ts
CHANGED
|
@@ -464,7 +464,7 @@ type UnlinkResult = {
|
|
|
464
464
|
* OTP, a dismissed Game Center sheet and a 429 all leave `getUserSync()` and
|
|
465
465
|
* the stored refresh token exactly as they were.
|
|
466
466
|
*/
|
|
467
|
-
type AuthErrorKind = "network" | "server" | "rate_limited" | "invalid_credential" | "account_locked" | "credential_in_use" | "last_credential" | "already_identified" | "cancelled" | "config" | "unknown";
|
|
467
|
+
type AuthErrorKind = "network" | "server" | "rate_limited" | "invalid_credential" | "account_locked" | "credential_in_use" | "last_credential" | "recent_auth_required" | "already_identified" | "cancelled" | "config" | "unknown";
|
|
468
468
|
declare class AuthError extends Error {
|
|
469
469
|
code: string;
|
|
470
470
|
/**
|
|
@@ -1109,6 +1109,16 @@ declare class Auth {
|
|
|
1109
1109
|
recoveryCodes: string[];
|
|
1110
1110
|
}>;
|
|
1111
1111
|
confirmMfa(code: string): Promise<boolean>;
|
|
1112
|
+
/**
|
|
1113
|
+
* Disable MFA.
|
|
1114
|
+
*
|
|
1115
|
+
* ⚠ STEP-UP gated (s58.319): a stale `auth_time` is refused with 403
|
|
1116
|
+
* `RECENT_AUTH_REQUIRED` / kind `recent_auth_required`.
|
|
1117
|
+
*
|
|
1118
|
+
* ⚠ Discarded its response until s58.335, and `request()` never throws on a
|
|
1119
|
+
* non-2xx (it warns and returns the Response), so the refusal had nowhere to
|
|
1120
|
+
* surface — the app reported MFA as off while TOTP stayed enrolled.
|
|
1121
|
+
*/
|
|
1112
1122
|
disableMfa(): Promise<void>;
|
|
1113
1123
|
listMySessions(): Promise<Array<{
|
|
1114
1124
|
id: string;
|
|
@@ -1117,7 +1127,14 @@ declare class Auth {
|
|
|
1117
1127
|
lastUsedAt: string | null;
|
|
1118
1128
|
createdAt: string;
|
|
1119
1129
|
}>>;
|
|
1130
|
+
/**
|
|
1131
|
+
* Revoke one of the caller's own sessions ("sign out that device").
|
|
1132
|
+
* ⚠ Discarded its response until s58.335 — a "sign out this device" button
|
|
1133
|
+
* that reports success on a failure is the one place a user acts on the claim
|
|
1134
|
+
* and then stops worrying.
|
|
1135
|
+
*/
|
|
1120
1136
|
revokeSession(sessionId: string): Promise<void>;
|
|
1137
|
+
/** Revoke every session for the caller. Same reporting defect as `revokeSession`. */
|
|
1121
1138
|
revokeAllSessions(): Promise<void>;
|
|
1122
1139
|
/**
|
|
1123
1140
|
* Delete the signed-in user's account (Apple App Store Guideline 5.1.1(v)).
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,12 @@ async function getAsyncStorage() {
|
|
|
20
20
|
})();
|
|
21
21
|
return asyncStoragePromise;
|
|
22
22
|
}
|
|
23
|
+
var warned = /* @__PURE__ */ new Set();
|
|
24
|
+
function warnOnce(key, message) {
|
|
25
|
+
if (warned.has(key)) return;
|
|
26
|
+
warned.add(key);
|
|
27
|
+
console.warn(message);
|
|
28
|
+
}
|
|
23
29
|
var Storage = class {
|
|
24
30
|
constructor(opts = {}) {
|
|
25
31
|
this.cache = /* @__PURE__ */ new Map();
|
|
@@ -28,6 +34,12 @@ var Storage = class {
|
|
|
28
34
|
this.secureKeys = new Set(opts.secureKeys ?? []);
|
|
29
35
|
this.prefix = opts.prefix ?? DEFAULT_PREFIX;
|
|
30
36
|
this.securePrefix = opts.prefix ?? "";
|
|
37
|
+
if (this.secure === null && this.secureKeys.size > 0) {
|
|
38
|
+
warnOnce(
|
|
39
|
+
"no-secure-adapter",
|
|
40
|
+
"[sendora] No `secureStorage` adapter supplied \u2014 auth tokens (refresh token, access token, cached user) will be stored in PLAIN AsyncStorage, which is included in iOS/Android device backups. Pass `secureStorage` in init() with a Keychain/Keystore-backed adapter (e.g. expo-secure-store). The session still persists either way; this is about where the token rests."
|
|
41
|
+
);
|
|
42
|
+
}
|
|
31
43
|
}
|
|
32
44
|
/** The adapter-facing name for a key. Bare by default; see `prefix`. */
|
|
33
45
|
secureName(key) {
|
|
@@ -81,6 +93,10 @@ var Storage = class {
|
|
|
81
93
|
}
|
|
82
94
|
}
|
|
83
95
|
} catch {
|
|
96
|
+
warnOnce(
|
|
97
|
+
"secure-read-degraded",
|
|
98
|
+
"[sendora] The `secureStorage` adapter failed on read; falling back to plain AsyncStorage for this session. Tokens are preserved but no longer encrypted at rest. Check your adapter."
|
|
99
|
+
);
|
|
84
100
|
if (store) {
|
|
85
101
|
try {
|
|
86
102
|
const legacy = await store.getItem(this.prefix + k);
|
|
@@ -97,6 +113,10 @@ var Storage = class {
|
|
|
97
113
|
this.cache.set(key, value);
|
|
98
114
|
if (this.isSecure(key)) {
|
|
99
115
|
void this.secure.setItem(this.secureName(key), value).catch(() => {
|
|
116
|
+
warnOnce(
|
|
117
|
+
"secure-write-degraded",
|
|
118
|
+
"[sendora] The `secureStorage` adapter failed on write; this value fell back to plain AsyncStorage. The session is preserved but this token is no longer encrypted at rest. Check your adapter."
|
|
119
|
+
);
|
|
100
120
|
void getAsyncStorage().then((store) => {
|
|
101
121
|
if (store) store.setItem(this.prefix + key, value).catch(() => {
|
|
102
122
|
});
|
|
@@ -163,7 +183,7 @@ var Storage = class {
|
|
|
163
183
|
// package.json
|
|
164
184
|
var package_default = {
|
|
165
185
|
name: "@sendoracloud/sdk-react-native",
|
|
166
|
-
version: "1.
|
|
186
|
+
version: "1.36.0",
|
|
167
187
|
description: "Sendora Cloud React Native + Expo SDK \u2014 analytics, identity, push-token registration, auth (incl. Game Center / Play Games), deep links (Branch / Firebase Dynamic Links parity). Auth + analytics + deep links work in Expo Go; push-token registration and the no-arg Game Center / Play Games sign-in require a Dev Client (EAS Build or `npx expo prebuild`).",
|
|
168
188
|
type: "module",
|
|
169
189
|
main: "./dist/index.cjs",
|
|
@@ -451,6 +471,12 @@ function classifyAuthErrorKind(code, status) {
|
|
|
451
471
|
return "credential_in_use";
|
|
452
472
|
case "LAST_CREDENTIAL":
|
|
453
473
|
return "last_credential";
|
|
474
|
+
// ⚠ MUST be a code case, not a status one. The tail of this function is
|
|
475
|
+
// `if (status >= 400) return "invalid_credential"`, which would otherwise
|
|
476
|
+
// claim the 403 and report a step-up refusal as a bad credential —
|
|
477
|
+
// documented as "needs NEW input", which is the opposite of the truth.
|
|
478
|
+
case "RECENT_AUTH_REQUIRED":
|
|
479
|
+
return "recent_auth_required";
|
|
454
480
|
case "NOT_ANONYMOUS":
|
|
455
481
|
case "FORBIDDEN_NON_ANONYMOUS":
|
|
456
482
|
return "already_identified";
|
|
@@ -1537,13 +1563,24 @@ var Auth = class {
|
|
|
1537
1563
|
const data = await this.unwrap(res, "MFA_CONFIRM_FAILED");
|
|
1538
1564
|
return Boolean(data.confirmed);
|
|
1539
1565
|
}
|
|
1566
|
+
/**
|
|
1567
|
+
* Disable MFA.
|
|
1568
|
+
*
|
|
1569
|
+
* ⚠ STEP-UP gated (s58.319): a stale `auth_time` is refused with 403
|
|
1570
|
+
* `RECENT_AUTH_REQUIRED` / kind `recent_auth_required`.
|
|
1571
|
+
*
|
|
1572
|
+
* ⚠ Discarded its response until s58.335, and `request()` never throws on a
|
|
1573
|
+
* non-2xx (it warns and returns the Response), so the refusal had nowhere to
|
|
1574
|
+
* surface — the app reported MFA as off while TOTP stayed enrolled.
|
|
1575
|
+
*/
|
|
1540
1576
|
async disableMfa() {
|
|
1541
|
-
await post(
|
|
1577
|
+
const res = await post(
|
|
1542
1578
|
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
1543
1579
|
"/api/v1/auth-service/mfa/disable",
|
|
1544
1580
|
{},
|
|
1545
1581
|
this.bearerHeaders()
|
|
1546
1582
|
);
|
|
1583
|
+
await this.unwrap(res, "MFA_DISABLE_FAILED");
|
|
1547
1584
|
}
|
|
1548
1585
|
// ============================================================
|
|
1549
1586
|
// DEVICE SESSIONS (Bearer-authenticated)
|
|
@@ -1558,19 +1595,28 @@ var Auth = class {
|
|
|
1558
1595
|
const parsed = await res.json();
|
|
1559
1596
|
return Array.isArray(parsed.data) ? parsed.data : [];
|
|
1560
1597
|
}
|
|
1598
|
+
/**
|
|
1599
|
+
* Revoke one of the caller's own sessions ("sign out that device").
|
|
1600
|
+
* ⚠ Discarded its response until s58.335 — a "sign out this device" button
|
|
1601
|
+
* that reports success on a failure is the one place a user acts on the claim
|
|
1602
|
+
* and then stops worrying.
|
|
1603
|
+
*/
|
|
1561
1604
|
async revokeSession(sessionId) {
|
|
1562
|
-
await del(
|
|
1605
|
+
const res = await del(
|
|
1563
1606
|
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
1564
1607
|
`/api/v1/auth-service/sessions/me/${encodeURIComponent(sessionId)}`,
|
|
1565
1608
|
this.bearerHeaders()
|
|
1566
1609
|
);
|
|
1610
|
+
await this.unwrap(res, "SESSION_REVOKE_FAILED");
|
|
1567
1611
|
}
|
|
1612
|
+
/** Revoke every session for the caller. Same reporting defect as `revokeSession`. */
|
|
1568
1613
|
async revokeAllSessions() {
|
|
1569
|
-
await del(
|
|
1614
|
+
const res = await del(
|
|
1570
1615
|
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
1571
1616
|
"/api/v1/auth-service/sessions/me",
|
|
1572
1617
|
this.bearerHeaders()
|
|
1573
1618
|
);
|
|
1619
|
+
await this.unwrap(res, "SESSION_REVOKE_ALL_FAILED");
|
|
1574
1620
|
}
|
|
1575
1621
|
/**
|
|
1576
1622
|
* Delete the signed-in user's account (Apple App Store Guideline 5.1.1(v)).
|
|
@@ -1736,7 +1782,10 @@ var Auth = class {
|
|
|
1736
1782
|
if (!res) throw new AuthError("NETWORK_ERROR", "Network request failed");
|
|
1737
1783
|
const parsed = await res.json().catch(() => ({}));
|
|
1738
1784
|
if (!res.ok || !parsed.success) {
|
|
1739
|
-
throw new AuthError(parsed.error?.code ?? errCode, parsed.error?.message ?? `HTTP ${res.status}
|
|
1785
|
+
throw new AuthError(parsed.error?.code ?? errCode, parsed.error?.message ?? `HTTP ${res.status}`, {
|
|
1786
|
+
status: res.status,
|
|
1787
|
+
retryAfterSeconds: readRetryAfterSeconds(parsed)
|
|
1788
|
+
});
|
|
1740
1789
|
}
|
|
1741
1790
|
return parsed.data;
|
|
1742
1791
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendoracloud/sdk-react-native",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.0",
|
|
4
4
|
"description": "Sendora Cloud React Native + Expo SDK — analytics, identity, push-token registration, auth (incl. Game Center / Play Games), deep links (Branch / Firebase Dynamic Links parity). Auth + analytics + deep links work in Expo Go; push-token registration and the no-arg Game Center / Play Games sign-in require a Dev Client (EAS Build or `npx expo prebuild`).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|