@sendoracloud/sdk-react-native 1.34.0 → 1.35.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 -2
- package/dist/index.d.cts +38 -2
- package/dist/index.d.ts +38 -2
- package/dist/index.js +54 -2
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -208,7 +208,7 @@ var Storage = class {
|
|
|
208
208
|
// package.json
|
|
209
209
|
var package_default = {
|
|
210
210
|
name: "@sendoracloud/sdk-react-native",
|
|
211
|
-
version: "1.
|
|
211
|
+
version: "1.35.0",
|
|
212
212
|
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
213
|
type: "module",
|
|
214
214
|
main: "./dist/index.cjs",
|
|
@@ -264,7 +264,7 @@ var package_default = {
|
|
|
264
264
|
scripts: {
|
|
265
265
|
build: "tsup src/index.ts src/contact-widget.tsx --format esm,cjs --dts --clean --external react --external react-native --external react-native-webview",
|
|
266
266
|
typecheck: "tsc --noEmit",
|
|
267
|
-
test: "tsx test/secure-storage.test.ts && tsx test/integration-storage.test.ts && tsx test/plugin.test.ts && tsx test/game-auth.test.ts && tsx test/link.test.ts && tsx test/session-preservation.test.ts && tsx test/credential-collision.test.ts && tsx test/token-expiry.test.ts"
|
|
267
|
+
test: "tsx test/secure-storage.test.ts && tsx test/integration-storage.test.ts && tsx test/plugin.test.ts && tsx test/game-auth.test.ts && tsx test/link.test.ts && tsx test/session-preservation.test.ts && tsx test/credential-collision.test.ts && tsx test/token-expiry.test.ts && tsx test/unlink.test.ts"
|
|
268
268
|
},
|
|
269
269
|
devDependencies: {
|
|
270
270
|
"@types/react": "^19.2.16",
|
|
@@ -494,6 +494,8 @@ function classifyAuthErrorKind(code, status) {
|
|
|
494
494
|
return "account_locked";
|
|
495
495
|
case "CREDENTIAL_IN_USE":
|
|
496
496
|
return "credential_in_use";
|
|
497
|
+
case "LAST_CREDENTIAL":
|
|
498
|
+
return "last_credential";
|
|
497
499
|
case "NOT_ANONYMOUS":
|
|
498
500
|
case "FORBIDDEN_NON_ANONYMOUS":
|
|
499
501
|
return "already_identified";
|
|
@@ -1333,6 +1335,56 @@ var Auth = class {
|
|
|
1333
1335
|
}
|
|
1334
1336
|
return { identities: parsed.data.identities ?? [], hasPassword: Boolean(parsed.data.hasPassword) };
|
|
1335
1337
|
}
|
|
1338
|
+
/**
|
|
1339
|
+
* Remove one linked provider from the signed-in account.
|
|
1340
|
+
*
|
|
1341
|
+
* The write half of `listLinkedIdentities()` — what a "Disconnect" button
|
|
1342
|
+
* next to each entry on a Connected Accounts screen calls.
|
|
1343
|
+
*
|
|
1344
|
+
* ⚠ The server REFUSES to remove the last way into the account, with
|
|
1345
|
+
* `AuthError` `code: "LAST_CREDENTIAL"` / `kind: "last_credential"`. An
|
|
1346
|
+
* account with no credentials still exists and still holds the user's data,
|
|
1347
|
+
* but nothing can ever authenticate into it again — so this is a permanent
|
|
1348
|
+
* lockout, not an inconvenience. A password counts as a credential.
|
|
1349
|
+
*
|
|
1350
|
+
* Prefer to prevent the tap rather than explain the refusal: read
|
|
1351
|
+
* `listLinkedIdentities()` and disable Disconnect when
|
|
1352
|
+
* `identities.length + (hasPassword ? 1 : 0) <= 1`. The error is the
|
|
1353
|
+
* backstop, not the UX.
|
|
1354
|
+
*
|
|
1355
|
+
* Throws `NOT_SIGNED_IN` when there is no session, and `NOT_FOUND` when the
|
|
1356
|
+
* provider is not linked to this account. Removing an already-absent
|
|
1357
|
+
* provider is NOT treated as success — a silent no-op would let a buggy
|
|
1358
|
+
* screen report "disconnected" for a credential that is still attached.
|
|
1359
|
+
*/
|
|
1360
|
+
async unlink(provider) {
|
|
1361
|
+
const token = await this.getAccessToken();
|
|
1362
|
+
if (!token) throw new AuthError("NOT_SIGNED_IN", "Sign in before unlinking an identity");
|
|
1363
|
+
const res = await del(
|
|
1364
|
+
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
1365
|
+
`/api/v1/auth-service/me/identities/${encodeURIComponent(provider)}`,
|
|
1366
|
+
{ Authorization: `Bearer ${token}` }
|
|
1367
|
+
);
|
|
1368
|
+
if (!res) throw new AuthError("NETWORK_ERROR", "Failed to unlink identity");
|
|
1369
|
+
let parsed;
|
|
1370
|
+
try {
|
|
1371
|
+
parsed = await res.json();
|
|
1372
|
+
} catch {
|
|
1373
|
+
throw new AuthError("PARSE_ERROR", `HTTP ${res.status}`);
|
|
1374
|
+
}
|
|
1375
|
+
if (!parsed.success || !parsed.data) {
|
|
1376
|
+
throw new AuthError(
|
|
1377
|
+
parsed.error?.code ?? "UNLINK_FAILED",
|
|
1378
|
+
parsed.error?.message ?? "Failed to unlink identity",
|
|
1379
|
+
{ status: res.status }
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
return {
|
|
1383
|
+
provider: parsed.data.provider ?? provider,
|
|
1384
|
+
removed: Number(parsed.data.removed ?? 0),
|
|
1385
|
+
remaining: Number(parsed.data.remaining ?? 0)
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1336
1388
|
/**
|
|
1337
1389
|
* Shared gaming-identity sign-in. Mirrors `loginSocial`'s anon-takeover +
|
|
1338
1390
|
* ADR-025 link-in-place handling: reads the anon refresh BEFORE wiping local
|
package/dist/index.d.cts
CHANGED
|
@@ -442,6 +442,19 @@ type LinkedIdentitiesResponse = {
|
|
|
442
442
|
identities: LinkedIdentity[];
|
|
443
443
|
hasPassword: boolean;
|
|
444
444
|
};
|
|
445
|
+
/**
|
|
446
|
+
* Result of removing one provider from the signed-in account.
|
|
447
|
+
*
|
|
448
|
+
* `removed` can exceed 1: an account may hold more than one row for a provider
|
|
449
|
+
* (distinct provider user ids across projects), and unlinking takes all of them
|
|
450
|
+
* — the floor counts them all as leaving, so reporting only one would be a lie
|
|
451
|
+
* a caller could act on.
|
|
452
|
+
*/
|
|
453
|
+
type UnlinkResult = {
|
|
454
|
+
provider: string;
|
|
455
|
+
removed: number;
|
|
456
|
+
remaining: number;
|
|
457
|
+
};
|
|
445
458
|
/**
|
|
446
459
|
* Closed set of auth failure categories (1.28.0). Branch on `kind` instead of
|
|
447
460
|
* string-matching the ~20 raw `code`s the backend and transport can produce.
|
|
@@ -451,7 +464,7 @@ type LinkedIdentitiesResponse = {
|
|
|
451
464
|
* OTP, a dismissed Game Center sheet and a 429 all leave `getUserSync()` and
|
|
452
465
|
* the stored refresh token exactly as they were.
|
|
453
466
|
*/
|
|
454
|
-
type AuthErrorKind = "network" | "server" | "rate_limited" | "invalid_credential" | "account_locked" | "credential_in_use" | "already_identified" | "cancelled" | "config" | "unknown";
|
|
467
|
+
type AuthErrorKind = "network" | "server" | "rate_limited" | "invalid_credential" | "account_locked" | "credential_in_use" | "last_credential" | "already_identified" | "cancelled" | "config" | "unknown";
|
|
455
468
|
declare class AuthError extends Error {
|
|
456
469
|
code: string;
|
|
457
470
|
/**
|
|
@@ -1034,6 +1047,29 @@ declare class Auth {
|
|
|
1034
1047
|
* `deleteAccount`). Firebase `user.providerData` / Supabase `user.identities`.
|
|
1035
1048
|
*/
|
|
1036
1049
|
listLinkedIdentities(): Promise<LinkedIdentitiesResponse>;
|
|
1050
|
+
/**
|
|
1051
|
+
* Remove one linked provider from the signed-in account.
|
|
1052
|
+
*
|
|
1053
|
+
* The write half of `listLinkedIdentities()` — what a "Disconnect" button
|
|
1054
|
+
* next to each entry on a Connected Accounts screen calls.
|
|
1055
|
+
*
|
|
1056
|
+
* ⚠ The server REFUSES to remove the last way into the account, with
|
|
1057
|
+
* `AuthError` `code: "LAST_CREDENTIAL"` / `kind: "last_credential"`. An
|
|
1058
|
+
* account with no credentials still exists and still holds the user's data,
|
|
1059
|
+
* but nothing can ever authenticate into it again — so this is a permanent
|
|
1060
|
+
* lockout, not an inconvenience. A password counts as a credential.
|
|
1061
|
+
*
|
|
1062
|
+
* Prefer to prevent the tap rather than explain the refusal: read
|
|
1063
|
+
* `listLinkedIdentities()` and disable Disconnect when
|
|
1064
|
+
* `identities.length + (hasPassword ? 1 : 0) <= 1`. The error is the
|
|
1065
|
+
* backstop, not the UX.
|
|
1066
|
+
*
|
|
1067
|
+
* Throws `NOT_SIGNED_IN` when there is no session, and `NOT_FOUND` when the
|
|
1068
|
+
* provider is not linked to this account. Removing an already-absent
|
|
1069
|
+
* provider is NOT treated as success — a silent no-op would let a buggy
|
|
1070
|
+
* screen report "disconnected" for a credential that is still attached.
|
|
1071
|
+
*/
|
|
1072
|
+
unlink(provider: string): Promise<UnlinkResult>;
|
|
1037
1073
|
/**
|
|
1038
1074
|
* Shared gaming-identity sign-in. Mirrors `loginSocial`'s anon-takeover +
|
|
1039
1075
|
* ADR-025 link-in-place handling: reads the anon refresh BEFORE wiping local
|
|
@@ -2038,4 +2074,4 @@ declare class SendoraSDK {
|
|
|
2038
2074
|
}
|
|
2039
2075
|
declare const SendoraCloud: SendoraSDK;
|
|
2040
2076
|
|
|
2041
|
-
export { AlreadyIdentifiedError, type AnonRetirementOutcome, type AttachLinkingApiOptions, Auth, AuthError, type AuthErrorKind, type AuthSignedOutReason, type AuthStateChange, type AuthTokens, type AuthUser, type CredentialCollisionPolicy, CredentialInUseError, type DeletionCancelledEvent, type DeviceTakeoverEvent, EmailAlreadyTakenError, type GameSignInOptions, type IdentifyTraits, type LinkCreateInput, type LinkCreateResult, type LinkData, LinkError, type LinkErrorCode, type LinkMatchInput, type LinkOpenedEvent, type LinkOpenedHandler, type LinkStats, type LinkedIdentitiesResponse, type LinkedIdentity, Links, type PushTokenReceipt, type PushTokenRegistration, SendoraCloud, type SendoraConfig, type TrackProperties, computeDeviceFingerprint, SendoraCloud as default, extractShortcodeFromUrl, getPlayInstallReferrer };
|
|
2077
|
+
export { AlreadyIdentifiedError, type AnonRetirementOutcome, type AttachLinkingApiOptions, Auth, AuthError, type AuthErrorKind, type AuthSignedOutReason, type AuthStateChange, type AuthTokens, type AuthUser, type CredentialCollisionPolicy, CredentialInUseError, type DeletionCancelledEvent, type DeviceTakeoverEvent, EmailAlreadyTakenError, type GameSignInOptions, type IdentifyTraits, type LinkCreateInput, type LinkCreateResult, type LinkData, LinkError, type LinkErrorCode, type LinkMatchInput, type LinkOpenedEvent, type LinkOpenedHandler, type LinkStats, type LinkedIdentitiesResponse, type LinkedIdentity, Links, type PushTokenReceipt, type PushTokenRegistration, SendoraCloud, type SendoraConfig, type TrackProperties, type UnlinkResult, computeDeviceFingerprint, SendoraCloud as default, extractShortcodeFromUrl, getPlayInstallReferrer };
|
package/dist/index.d.ts
CHANGED
|
@@ -442,6 +442,19 @@ type LinkedIdentitiesResponse = {
|
|
|
442
442
|
identities: LinkedIdentity[];
|
|
443
443
|
hasPassword: boolean;
|
|
444
444
|
};
|
|
445
|
+
/**
|
|
446
|
+
* Result of removing one provider from the signed-in account.
|
|
447
|
+
*
|
|
448
|
+
* `removed` can exceed 1: an account may hold more than one row for a provider
|
|
449
|
+
* (distinct provider user ids across projects), and unlinking takes all of them
|
|
450
|
+
* — the floor counts them all as leaving, so reporting only one would be a lie
|
|
451
|
+
* a caller could act on.
|
|
452
|
+
*/
|
|
453
|
+
type UnlinkResult = {
|
|
454
|
+
provider: string;
|
|
455
|
+
removed: number;
|
|
456
|
+
remaining: number;
|
|
457
|
+
};
|
|
445
458
|
/**
|
|
446
459
|
* Closed set of auth failure categories (1.28.0). Branch on `kind` instead of
|
|
447
460
|
* string-matching the ~20 raw `code`s the backend and transport can produce.
|
|
@@ -451,7 +464,7 @@ type LinkedIdentitiesResponse = {
|
|
|
451
464
|
* OTP, a dismissed Game Center sheet and a 429 all leave `getUserSync()` and
|
|
452
465
|
* the stored refresh token exactly as they were.
|
|
453
466
|
*/
|
|
454
|
-
type AuthErrorKind = "network" | "server" | "rate_limited" | "invalid_credential" | "account_locked" | "credential_in_use" | "already_identified" | "cancelled" | "config" | "unknown";
|
|
467
|
+
type AuthErrorKind = "network" | "server" | "rate_limited" | "invalid_credential" | "account_locked" | "credential_in_use" | "last_credential" | "already_identified" | "cancelled" | "config" | "unknown";
|
|
455
468
|
declare class AuthError extends Error {
|
|
456
469
|
code: string;
|
|
457
470
|
/**
|
|
@@ -1034,6 +1047,29 @@ declare class Auth {
|
|
|
1034
1047
|
* `deleteAccount`). Firebase `user.providerData` / Supabase `user.identities`.
|
|
1035
1048
|
*/
|
|
1036
1049
|
listLinkedIdentities(): Promise<LinkedIdentitiesResponse>;
|
|
1050
|
+
/**
|
|
1051
|
+
* Remove one linked provider from the signed-in account.
|
|
1052
|
+
*
|
|
1053
|
+
* The write half of `listLinkedIdentities()` — what a "Disconnect" button
|
|
1054
|
+
* next to each entry on a Connected Accounts screen calls.
|
|
1055
|
+
*
|
|
1056
|
+
* ⚠ The server REFUSES to remove the last way into the account, with
|
|
1057
|
+
* `AuthError` `code: "LAST_CREDENTIAL"` / `kind: "last_credential"`. An
|
|
1058
|
+
* account with no credentials still exists and still holds the user's data,
|
|
1059
|
+
* but nothing can ever authenticate into it again — so this is a permanent
|
|
1060
|
+
* lockout, not an inconvenience. A password counts as a credential.
|
|
1061
|
+
*
|
|
1062
|
+
* Prefer to prevent the tap rather than explain the refusal: read
|
|
1063
|
+
* `listLinkedIdentities()` and disable Disconnect when
|
|
1064
|
+
* `identities.length + (hasPassword ? 1 : 0) <= 1`. The error is the
|
|
1065
|
+
* backstop, not the UX.
|
|
1066
|
+
*
|
|
1067
|
+
* Throws `NOT_SIGNED_IN` when there is no session, and `NOT_FOUND` when the
|
|
1068
|
+
* provider is not linked to this account. Removing an already-absent
|
|
1069
|
+
* provider is NOT treated as success — a silent no-op would let a buggy
|
|
1070
|
+
* screen report "disconnected" for a credential that is still attached.
|
|
1071
|
+
*/
|
|
1072
|
+
unlink(provider: string): Promise<UnlinkResult>;
|
|
1037
1073
|
/**
|
|
1038
1074
|
* Shared gaming-identity sign-in. Mirrors `loginSocial`'s anon-takeover +
|
|
1039
1075
|
* ADR-025 link-in-place handling: reads the anon refresh BEFORE wiping local
|
|
@@ -2038,4 +2074,4 @@ declare class SendoraSDK {
|
|
|
2038
2074
|
}
|
|
2039
2075
|
declare const SendoraCloud: SendoraSDK;
|
|
2040
2076
|
|
|
2041
|
-
export { AlreadyIdentifiedError, type AnonRetirementOutcome, type AttachLinkingApiOptions, Auth, AuthError, type AuthErrorKind, type AuthSignedOutReason, type AuthStateChange, type AuthTokens, type AuthUser, type CredentialCollisionPolicy, CredentialInUseError, type DeletionCancelledEvent, type DeviceTakeoverEvent, EmailAlreadyTakenError, type GameSignInOptions, type IdentifyTraits, type LinkCreateInput, type LinkCreateResult, type LinkData, LinkError, type LinkErrorCode, type LinkMatchInput, type LinkOpenedEvent, type LinkOpenedHandler, type LinkStats, type LinkedIdentitiesResponse, type LinkedIdentity, Links, type PushTokenReceipt, type PushTokenRegistration, SendoraCloud, type SendoraConfig, type TrackProperties, computeDeviceFingerprint, SendoraCloud as default, extractShortcodeFromUrl, getPlayInstallReferrer };
|
|
2077
|
+
export { AlreadyIdentifiedError, type AnonRetirementOutcome, type AttachLinkingApiOptions, Auth, AuthError, type AuthErrorKind, type AuthSignedOutReason, type AuthStateChange, type AuthTokens, type AuthUser, type CredentialCollisionPolicy, CredentialInUseError, type DeletionCancelledEvent, type DeviceTakeoverEvent, EmailAlreadyTakenError, type GameSignInOptions, type IdentifyTraits, type LinkCreateInput, type LinkCreateResult, type LinkData, LinkError, type LinkErrorCode, type LinkMatchInput, type LinkOpenedEvent, type LinkOpenedHandler, type LinkStats, type LinkedIdentitiesResponse, type LinkedIdentity, Links, type PushTokenReceipt, type PushTokenRegistration, SendoraCloud, type SendoraConfig, type TrackProperties, type UnlinkResult, computeDeviceFingerprint, SendoraCloud as default, extractShortcodeFromUrl, getPlayInstallReferrer };
|
package/dist/index.js
CHANGED
|
@@ -163,7 +163,7 @@ var Storage = class {
|
|
|
163
163
|
// package.json
|
|
164
164
|
var package_default = {
|
|
165
165
|
name: "@sendoracloud/sdk-react-native",
|
|
166
|
-
version: "1.
|
|
166
|
+
version: "1.35.0",
|
|
167
167
|
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
168
|
type: "module",
|
|
169
169
|
main: "./dist/index.cjs",
|
|
@@ -219,7 +219,7 @@ var package_default = {
|
|
|
219
219
|
scripts: {
|
|
220
220
|
build: "tsup src/index.ts src/contact-widget.tsx --format esm,cjs --dts --clean --external react --external react-native --external react-native-webview",
|
|
221
221
|
typecheck: "tsc --noEmit",
|
|
222
|
-
test: "tsx test/secure-storage.test.ts && tsx test/integration-storage.test.ts && tsx test/plugin.test.ts && tsx test/game-auth.test.ts && tsx test/link.test.ts && tsx test/session-preservation.test.ts && tsx test/credential-collision.test.ts && tsx test/token-expiry.test.ts"
|
|
222
|
+
test: "tsx test/secure-storage.test.ts && tsx test/integration-storage.test.ts && tsx test/plugin.test.ts && tsx test/game-auth.test.ts && tsx test/link.test.ts && tsx test/session-preservation.test.ts && tsx test/credential-collision.test.ts && tsx test/token-expiry.test.ts && tsx test/unlink.test.ts"
|
|
223
223
|
},
|
|
224
224
|
devDependencies: {
|
|
225
225
|
"@types/react": "^19.2.16",
|
|
@@ -449,6 +449,8 @@ function classifyAuthErrorKind(code, status) {
|
|
|
449
449
|
return "account_locked";
|
|
450
450
|
case "CREDENTIAL_IN_USE":
|
|
451
451
|
return "credential_in_use";
|
|
452
|
+
case "LAST_CREDENTIAL":
|
|
453
|
+
return "last_credential";
|
|
452
454
|
case "NOT_ANONYMOUS":
|
|
453
455
|
case "FORBIDDEN_NON_ANONYMOUS":
|
|
454
456
|
return "already_identified";
|
|
@@ -1288,6 +1290,56 @@ var Auth = class {
|
|
|
1288
1290
|
}
|
|
1289
1291
|
return { identities: parsed.data.identities ?? [], hasPassword: Boolean(parsed.data.hasPassword) };
|
|
1290
1292
|
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Remove one linked provider from the signed-in account.
|
|
1295
|
+
*
|
|
1296
|
+
* The write half of `listLinkedIdentities()` — what a "Disconnect" button
|
|
1297
|
+
* next to each entry on a Connected Accounts screen calls.
|
|
1298
|
+
*
|
|
1299
|
+
* ⚠ The server REFUSES to remove the last way into the account, with
|
|
1300
|
+
* `AuthError` `code: "LAST_CREDENTIAL"` / `kind: "last_credential"`. An
|
|
1301
|
+
* account with no credentials still exists and still holds the user's data,
|
|
1302
|
+
* but nothing can ever authenticate into it again — so this is a permanent
|
|
1303
|
+
* lockout, not an inconvenience. A password counts as a credential.
|
|
1304
|
+
*
|
|
1305
|
+
* Prefer to prevent the tap rather than explain the refusal: read
|
|
1306
|
+
* `listLinkedIdentities()` and disable Disconnect when
|
|
1307
|
+
* `identities.length + (hasPassword ? 1 : 0) <= 1`. The error is the
|
|
1308
|
+
* backstop, not the UX.
|
|
1309
|
+
*
|
|
1310
|
+
* Throws `NOT_SIGNED_IN` when there is no session, and `NOT_FOUND` when the
|
|
1311
|
+
* provider is not linked to this account. Removing an already-absent
|
|
1312
|
+
* provider is NOT treated as success — a silent no-op would let a buggy
|
|
1313
|
+
* screen report "disconnected" for a credential that is still attached.
|
|
1314
|
+
*/
|
|
1315
|
+
async unlink(provider) {
|
|
1316
|
+
const token = await this.getAccessToken();
|
|
1317
|
+
if (!token) throw new AuthError("NOT_SIGNED_IN", "Sign in before unlinking an identity");
|
|
1318
|
+
const res = await del(
|
|
1319
|
+
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
1320
|
+
`/api/v1/auth-service/me/identities/${encodeURIComponent(provider)}`,
|
|
1321
|
+
{ Authorization: `Bearer ${token}` }
|
|
1322
|
+
);
|
|
1323
|
+
if (!res) throw new AuthError("NETWORK_ERROR", "Failed to unlink identity");
|
|
1324
|
+
let parsed;
|
|
1325
|
+
try {
|
|
1326
|
+
parsed = await res.json();
|
|
1327
|
+
} catch {
|
|
1328
|
+
throw new AuthError("PARSE_ERROR", `HTTP ${res.status}`);
|
|
1329
|
+
}
|
|
1330
|
+
if (!parsed.success || !parsed.data) {
|
|
1331
|
+
throw new AuthError(
|
|
1332
|
+
parsed.error?.code ?? "UNLINK_FAILED",
|
|
1333
|
+
parsed.error?.message ?? "Failed to unlink identity",
|
|
1334
|
+
{ status: res.status }
|
|
1335
|
+
);
|
|
1336
|
+
}
|
|
1337
|
+
return {
|
|
1338
|
+
provider: parsed.data.provider ?? provider,
|
|
1339
|
+
removed: Number(parsed.data.removed ?? 0),
|
|
1340
|
+
remaining: Number(parsed.data.remaining ?? 0)
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1291
1343
|
/**
|
|
1292
1344
|
* Shared gaming-identity sign-in. Mirrors `loginSocial`'s anon-takeover +
|
|
1293
1345
|
* ADR-025 link-in-place handling: reads the anon refresh BEFORE wiping local
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendoracloud/sdk-react-native",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.35.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",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"scripts": {
|
|
57
57
|
"build": "tsup src/index.ts src/contact-widget.tsx --format esm,cjs --dts --clean --external react --external react-native --external react-native-webview",
|
|
58
58
|
"typecheck": "tsc --noEmit",
|
|
59
|
-
"test": "tsx test/secure-storage.test.ts && tsx test/integration-storage.test.ts && tsx test/plugin.test.ts && tsx test/game-auth.test.ts && tsx test/link.test.ts && tsx test/session-preservation.test.ts && tsx test/credential-collision.test.ts && tsx test/token-expiry.test.ts"
|
|
59
|
+
"test": "tsx test/secure-storage.test.ts && tsx test/integration-storage.test.ts && tsx test/plugin.test.ts && tsx test/game-auth.test.ts && tsx test/link.test.ts && tsx test/session-preservation.test.ts && tsx test/credential-collision.test.ts && tsx test/token-expiry.test.ts && tsx test/unlink.test.ts"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/react": "^19.2.16",
|