@sendoracloud/sdk-react-native 0.10.1 → 0.10.2
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 +26 -6
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +26 -6
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -283,11 +283,29 @@ var Auth = class {
|
|
|
283
283
|
return data.user;
|
|
284
284
|
});
|
|
285
285
|
}
|
|
286
|
+
/**
|
|
287
|
+
* Create an email/password account.
|
|
288
|
+
*
|
|
289
|
+
* Industry-standard upgrade-first flow (matches Firebase
|
|
290
|
+
* `linkWithCredential`, Auth0 anonymous-merge, Supabase
|
|
291
|
+
* `linkIdentity`): when a refresh token is present in storage we
|
|
292
|
+
* try `/auth-service/upgrade` first — backend validates the
|
|
293
|
+
* refresh, checks the bound user is anonymous, and promotes in
|
|
294
|
+
* place preserving `user.id`. If the bound user is NOT anonymous
|
|
295
|
+
* (already identified, expired refresh, etc.), backend rejects
|
|
296
|
+
* with FORBIDDEN_NON_ANONYMOUS / INVALID_REFRESH and we fall back
|
|
297
|
+
* to a fresh /signup.
|
|
298
|
+
*
|
|
299
|
+
* Why we don't gate on the cached `this.user.isAnonymous`
|
|
300
|
+
* boolean: the in-memory user can be stale during cold start or
|
|
301
|
+
* fast-refresh races. The refresh token in storage is the
|
|
302
|
+
* authoritative signal — if it's there, the upgrade path is
|
|
303
|
+
* worth attempting; backend has the source of truth.
|
|
304
|
+
*/
|
|
286
305
|
signUp(email, password, opts) {
|
|
287
306
|
return this.serialize(async () => {
|
|
288
307
|
const refresh = this.hooks.storage.get(REFRESH_KEY);
|
|
289
|
-
|
|
290
|
-
if (isAnonymous && refresh) {
|
|
308
|
+
if (refresh) {
|
|
291
309
|
try {
|
|
292
310
|
const data = await this.callAuth("/api/v1/auth-service/upgrade", {
|
|
293
311
|
refreshToken: refresh,
|
|
@@ -301,11 +319,13 @@ var Auth = class {
|
|
|
301
319
|
if (err instanceof AuthError && (err.code === "CONFLICT" || err.code === "EMAIL_ALREADY_TAKEN")) {
|
|
302
320
|
throw new EmailAlreadyTakenError(err.message);
|
|
303
321
|
}
|
|
304
|
-
|
|
322
|
+
if (err instanceof AuthError && (err.code === "FORBIDDEN_NON_ANONYMOUS" || err.code === "INVALID_REFRESH" || err.code === "UNAUTHORIZED" || err.code === "REFRESH_EXPIRED")) {
|
|
323
|
+
await this.wipeLocalIdentity();
|
|
324
|
+
} else {
|
|
325
|
+
throw err;
|
|
326
|
+
}
|
|
305
327
|
}
|
|
306
328
|
}
|
|
307
|
-
const wasIdentified = this.user !== null && this.user.isAnonymous === false;
|
|
308
|
-
if (wasIdentified) await this.wipeLocalIdentity();
|
|
309
329
|
try {
|
|
310
330
|
const data = await this.callAuth("/api/v1/auth-service/signup", {
|
|
311
331
|
email,
|
|
@@ -770,7 +790,7 @@ function decodeJwtPayload(token) {
|
|
|
770
790
|
}
|
|
771
791
|
|
|
772
792
|
// src/index.ts
|
|
773
|
-
var SDK_VERSION = "0.10.
|
|
793
|
+
var SDK_VERSION = "0.10.2";
|
|
774
794
|
var DEFAULT_API_URL = "https://api.sendoracloud.com";
|
|
775
795
|
var ANON_KEY = "anon_id";
|
|
776
796
|
var USER_ID_KEY = "user_id";
|
package/dist/index.d.cts
CHANGED
|
@@ -123,6 +123,25 @@ declare class Auth {
|
|
|
123
123
|
name?: string;
|
|
124
124
|
metadata?: Record<string, unknown>;
|
|
125
125
|
}): Promise<AuthUser>;
|
|
126
|
+
/**
|
|
127
|
+
* Create an email/password account.
|
|
128
|
+
*
|
|
129
|
+
* Industry-standard upgrade-first flow (matches Firebase
|
|
130
|
+
* `linkWithCredential`, Auth0 anonymous-merge, Supabase
|
|
131
|
+
* `linkIdentity`): when a refresh token is present in storage we
|
|
132
|
+
* try `/auth-service/upgrade` first — backend validates the
|
|
133
|
+
* refresh, checks the bound user is anonymous, and promotes in
|
|
134
|
+
* place preserving `user.id`. If the bound user is NOT anonymous
|
|
135
|
+
* (already identified, expired refresh, etc.), backend rejects
|
|
136
|
+
* with FORBIDDEN_NON_ANONYMOUS / INVALID_REFRESH and we fall back
|
|
137
|
+
* to a fresh /signup.
|
|
138
|
+
*
|
|
139
|
+
* Why we don't gate on the cached `this.user.isAnonymous`
|
|
140
|
+
* boolean: the in-memory user can be stale during cold start or
|
|
141
|
+
* fast-refresh races. The refresh token in storage is the
|
|
142
|
+
* authoritative signal — if it's there, the upgrade path is
|
|
143
|
+
* worth attempting; backend has the source of truth.
|
|
144
|
+
*/
|
|
126
145
|
signUp(email: string, password: string, opts?: {
|
|
127
146
|
name?: string;
|
|
128
147
|
metadata?: Record<string, unknown>;
|
package/dist/index.d.ts
CHANGED
|
@@ -123,6 +123,25 @@ declare class Auth {
|
|
|
123
123
|
name?: string;
|
|
124
124
|
metadata?: Record<string, unknown>;
|
|
125
125
|
}): Promise<AuthUser>;
|
|
126
|
+
/**
|
|
127
|
+
* Create an email/password account.
|
|
128
|
+
*
|
|
129
|
+
* Industry-standard upgrade-first flow (matches Firebase
|
|
130
|
+
* `linkWithCredential`, Auth0 anonymous-merge, Supabase
|
|
131
|
+
* `linkIdentity`): when a refresh token is present in storage we
|
|
132
|
+
* try `/auth-service/upgrade` first — backend validates the
|
|
133
|
+
* refresh, checks the bound user is anonymous, and promotes in
|
|
134
|
+
* place preserving `user.id`. If the bound user is NOT anonymous
|
|
135
|
+
* (already identified, expired refresh, etc.), backend rejects
|
|
136
|
+
* with FORBIDDEN_NON_ANONYMOUS / INVALID_REFRESH and we fall back
|
|
137
|
+
* to a fresh /signup.
|
|
138
|
+
*
|
|
139
|
+
* Why we don't gate on the cached `this.user.isAnonymous`
|
|
140
|
+
* boolean: the in-memory user can be stale during cold start or
|
|
141
|
+
* fast-refresh races. The refresh token in storage is the
|
|
142
|
+
* authoritative signal — if it's there, the upgrade path is
|
|
143
|
+
* worth attempting; backend has the source of truth.
|
|
144
|
+
*/
|
|
126
145
|
signUp(email: string, password: string, opts?: {
|
|
127
146
|
name?: string;
|
|
128
147
|
metadata?: Record<string, unknown>;
|
package/dist/index.js
CHANGED
|
@@ -243,11 +243,29 @@ var Auth = class {
|
|
|
243
243
|
return data.user;
|
|
244
244
|
});
|
|
245
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Create an email/password account.
|
|
248
|
+
*
|
|
249
|
+
* Industry-standard upgrade-first flow (matches Firebase
|
|
250
|
+
* `linkWithCredential`, Auth0 anonymous-merge, Supabase
|
|
251
|
+
* `linkIdentity`): when a refresh token is present in storage we
|
|
252
|
+
* try `/auth-service/upgrade` first — backend validates the
|
|
253
|
+
* refresh, checks the bound user is anonymous, and promotes in
|
|
254
|
+
* place preserving `user.id`. If the bound user is NOT anonymous
|
|
255
|
+
* (already identified, expired refresh, etc.), backend rejects
|
|
256
|
+
* with FORBIDDEN_NON_ANONYMOUS / INVALID_REFRESH and we fall back
|
|
257
|
+
* to a fresh /signup.
|
|
258
|
+
*
|
|
259
|
+
* Why we don't gate on the cached `this.user.isAnonymous`
|
|
260
|
+
* boolean: the in-memory user can be stale during cold start or
|
|
261
|
+
* fast-refresh races. The refresh token in storage is the
|
|
262
|
+
* authoritative signal — if it's there, the upgrade path is
|
|
263
|
+
* worth attempting; backend has the source of truth.
|
|
264
|
+
*/
|
|
246
265
|
signUp(email, password, opts) {
|
|
247
266
|
return this.serialize(async () => {
|
|
248
267
|
const refresh = this.hooks.storage.get(REFRESH_KEY);
|
|
249
|
-
|
|
250
|
-
if (isAnonymous && refresh) {
|
|
268
|
+
if (refresh) {
|
|
251
269
|
try {
|
|
252
270
|
const data = await this.callAuth("/api/v1/auth-service/upgrade", {
|
|
253
271
|
refreshToken: refresh,
|
|
@@ -261,11 +279,13 @@ var Auth = class {
|
|
|
261
279
|
if (err instanceof AuthError && (err.code === "CONFLICT" || err.code === "EMAIL_ALREADY_TAKEN")) {
|
|
262
280
|
throw new EmailAlreadyTakenError(err.message);
|
|
263
281
|
}
|
|
264
|
-
|
|
282
|
+
if (err instanceof AuthError && (err.code === "FORBIDDEN_NON_ANONYMOUS" || err.code === "INVALID_REFRESH" || err.code === "UNAUTHORIZED" || err.code === "REFRESH_EXPIRED")) {
|
|
283
|
+
await this.wipeLocalIdentity();
|
|
284
|
+
} else {
|
|
285
|
+
throw err;
|
|
286
|
+
}
|
|
265
287
|
}
|
|
266
288
|
}
|
|
267
|
-
const wasIdentified = this.user !== null && this.user.isAnonymous === false;
|
|
268
|
-
if (wasIdentified) await this.wipeLocalIdentity();
|
|
269
289
|
try {
|
|
270
290
|
const data = await this.callAuth("/api/v1/auth-service/signup", {
|
|
271
291
|
email,
|
|
@@ -730,7 +750,7 @@ function decodeJwtPayload(token) {
|
|
|
730
750
|
}
|
|
731
751
|
|
|
732
752
|
// src/index.ts
|
|
733
|
-
var SDK_VERSION = "0.10.
|
|
753
|
+
var SDK_VERSION = "0.10.2";
|
|
734
754
|
var DEFAULT_API_URL = "https://api.sendoracloud.com";
|
|
735
755
|
var ANON_KEY = "anon_id";
|
|
736
756
|
var USER_ID_KEY = "user_id";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendoracloud/sdk-react-native",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "Sendora Cloud React Native + Expo SDK — analytics, identity, push-token registration, auth. Expo Go compatible, no native modules beyond AsyncStorage.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|