@sendoracloud/sdk-react-native 1.0.1 → 1.0.3

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 CHANGED
@@ -434,11 +434,18 @@ var Auth = class {
434
434
  */
435
435
  loginSocial(input) {
436
436
  return this.serialize(async () => {
437
+ let prevAnonRefreshToken;
438
+ if (this.user?.isAnonymous) {
439
+ const stashed = this.hooks.storage.get(REFRESH_KEY);
440
+ if (stashed) prevAnonRefreshToken = stashed;
441
+ }
437
442
  if (this.user !== null) await this.wipeLocalIdentity();
443
+ const payload = { ...input };
444
+ if (prevAnonRefreshToken) payload.prevAnonRefreshToken = prevAnonRefreshToken;
438
445
  const res = await post(
439
446
  { apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
440
447
  "/api/v1/auth-service/login/social",
441
- input
448
+ payload
442
449
  );
443
450
  if (!res) throw new AuthError("NETWORK_ERROR", "Network request failed");
444
451
  let parsed;
@@ -478,16 +485,30 @@ var Auth = class {
478
485
  signInWithDiscord(code, redirectUri) {
479
486
  return this.loginSocial({ provider: "discord", code, redirectUri });
480
487
  }
488
+ /**
489
+ * Read the stored anon refresh token if (and only if) the local
490
+ * subject is currently anonymous. Used by every identified-session
491
+ * mint path so the backend can run device-takeover (s58.111 +
492
+ * s58.112). Returns `undefined` when not anonymous — never forward
493
+ * an identified user's own refresh token.
494
+ */
495
+ readPrevAnonRefreshToken() {
496
+ if (!this.user?.isAnonymous) return void 0;
497
+ return this.hooks.storage.get(REFRESH_KEY) ?? void 0;
498
+ }
481
499
  /**
482
500
  * Exchange the MFA challenge token from `signIn` for a real session
483
501
  * by submitting a TOTP or recovery code from the user's authenticator.
484
502
  */
485
503
  challengeMfa(mfaChallengeToken, code) {
486
504
  return this.serialize(async () => {
487
- const data = await this.callAuth("/api/v1/auth-service/mfa/challenge", {
505
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
506
+ const body = {
488
507
  challengeToken: mfaChallengeToken,
489
508
  code
490
- });
509
+ };
510
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
511
+ const data = await this.callAuth("/api/v1/auth-service/mfa/challenge", body);
491
512
  this.persist(data);
492
513
  return data.user;
493
514
  });
@@ -507,8 +528,11 @@ var Auth = class {
507
528
  }
508
529
  verifyMagicLink(token) {
509
530
  return this.serialize(async () => {
531
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
510
532
  if (this.user !== null) await this.wipeLocalIdentity();
511
- const data = await this.callAuth("/api/v1/auth-service/magic-link/verify", { token });
533
+ const body = { token };
534
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
535
+ const data = await this.callAuth("/api/v1/auth-service/magic-link/verify", body);
512
536
  this.persist(data);
513
537
  return data.user;
514
538
  });
@@ -528,8 +552,11 @@ var Auth = class {
528
552
  }
529
553
  verifyEmailOtp(email, code) {
530
554
  return this.serialize(async () => {
555
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
531
556
  if (this.user !== null) await this.wipeLocalIdentity();
532
- const data = await this.callAuth("/api/v1/auth-service/email-otp/verify", { email, code });
557
+ const body = { email, code };
558
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
559
+ const data = await this.callAuth("/api/v1/auth-service/email-otp/verify", body);
533
560
  this.persist(data);
534
561
  return data.user;
535
562
  });
package/dist/index.d.cts CHANGED
@@ -220,6 +220,14 @@ declare class Auth {
220
220
  signInWithLinkedIn(code: string, redirectUri: string): Promise<AuthUser>;
221
221
  signInWithFacebook(code: string, redirectUri: string): Promise<AuthUser>;
222
222
  signInWithDiscord(code: string, redirectUri: string): Promise<AuthUser>;
223
+ /**
224
+ * Read the stored anon refresh token if (and only if) the local
225
+ * subject is currently anonymous. Used by every identified-session
226
+ * mint path so the backend can run device-takeover (s58.111 +
227
+ * s58.112). Returns `undefined` when not anonymous — never forward
228
+ * an identified user's own refresh token.
229
+ */
230
+ private readPrevAnonRefreshToken;
223
231
  /**
224
232
  * Exchange the MFA challenge token from `signIn` for a real session
225
233
  * by submitting a TOTP or recovery code from the user's authenticator.
package/dist/index.d.ts CHANGED
@@ -220,6 +220,14 @@ declare class Auth {
220
220
  signInWithLinkedIn(code: string, redirectUri: string): Promise<AuthUser>;
221
221
  signInWithFacebook(code: string, redirectUri: string): Promise<AuthUser>;
222
222
  signInWithDiscord(code: string, redirectUri: string): Promise<AuthUser>;
223
+ /**
224
+ * Read the stored anon refresh token if (and only if) the local
225
+ * subject is currently anonymous. Used by every identified-session
226
+ * mint path so the backend can run device-takeover (s58.111 +
227
+ * s58.112). Returns `undefined` when not anonymous — never forward
228
+ * an identified user's own refresh token.
229
+ */
230
+ private readPrevAnonRefreshToken;
223
231
  /**
224
232
  * Exchange the MFA challenge token from `signIn` for a real session
225
233
  * by submitting a TOTP or recovery code from the user's authenticator.
package/dist/index.js CHANGED
@@ -391,11 +391,18 @@ var Auth = class {
391
391
  */
392
392
  loginSocial(input) {
393
393
  return this.serialize(async () => {
394
+ let prevAnonRefreshToken;
395
+ if (this.user?.isAnonymous) {
396
+ const stashed = this.hooks.storage.get(REFRESH_KEY);
397
+ if (stashed) prevAnonRefreshToken = stashed;
398
+ }
394
399
  if (this.user !== null) await this.wipeLocalIdentity();
400
+ const payload = { ...input };
401
+ if (prevAnonRefreshToken) payload.prevAnonRefreshToken = prevAnonRefreshToken;
395
402
  const res = await post(
396
403
  { apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
397
404
  "/api/v1/auth-service/login/social",
398
- input
405
+ payload
399
406
  );
400
407
  if (!res) throw new AuthError("NETWORK_ERROR", "Network request failed");
401
408
  let parsed;
@@ -435,16 +442,30 @@ var Auth = class {
435
442
  signInWithDiscord(code, redirectUri) {
436
443
  return this.loginSocial({ provider: "discord", code, redirectUri });
437
444
  }
445
+ /**
446
+ * Read the stored anon refresh token if (and only if) the local
447
+ * subject is currently anonymous. Used by every identified-session
448
+ * mint path so the backend can run device-takeover (s58.111 +
449
+ * s58.112). Returns `undefined` when not anonymous — never forward
450
+ * an identified user's own refresh token.
451
+ */
452
+ readPrevAnonRefreshToken() {
453
+ if (!this.user?.isAnonymous) return void 0;
454
+ return this.hooks.storage.get(REFRESH_KEY) ?? void 0;
455
+ }
438
456
  /**
439
457
  * Exchange the MFA challenge token from `signIn` for a real session
440
458
  * by submitting a TOTP or recovery code from the user's authenticator.
441
459
  */
442
460
  challengeMfa(mfaChallengeToken, code) {
443
461
  return this.serialize(async () => {
444
- const data = await this.callAuth("/api/v1/auth-service/mfa/challenge", {
462
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
463
+ const body = {
445
464
  challengeToken: mfaChallengeToken,
446
465
  code
447
- });
466
+ };
467
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
468
+ const data = await this.callAuth("/api/v1/auth-service/mfa/challenge", body);
448
469
  this.persist(data);
449
470
  return data.user;
450
471
  });
@@ -464,8 +485,11 @@ var Auth = class {
464
485
  }
465
486
  verifyMagicLink(token) {
466
487
  return this.serialize(async () => {
488
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
467
489
  if (this.user !== null) await this.wipeLocalIdentity();
468
- const data = await this.callAuth("/api/v1/auth-service/magic-link/verify", { token });
490
+ const body = { token };
491
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
492
+ const data = await this.callAuth("/api/v1/auth-service/magic-link/verify", body);
469
493
  this.persist(data);
470
494
  return data.user;
471
495
  });
@@ -485,8 +509,11 @@ var Auth = class {
485
509
  }
486
510
  verifyEmailOtp(email, code) {
487
511
  return this.serialize(async () => {
512
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
488
513
  if (this.user !== null) await this.wipeLocalIdentity();
489
- const data = await this.callAuth("/api/v1/auth-service/email-otp/verify", { email, code });
514
+ const body = { email, code };
515
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
516
+ const data = await this.callAuth("/api/v1/auth-service/email-otp/verify", body);
490
517
  this.persist(data);
491
518
  return data.user;
492
519
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendoracloud/sdk-react-native",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Sendora Cloud React Native + Expo SDK — analytics, identity, push-token registration, auth, deep links (Branch / Firebase Dynamic Links parity). Auth + analytics + deep links work in Expo Go; push token registration requires a Dev Client (EAS Build or `npx expo prebuild`).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",