@sendoracloud/sdk-react-native 0.13.0 → 0.14.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 CHANGED
@@ -235,21 +235,41 @@ var Auth = class {
235
235
  this.resolveReady = res;
236
236
  });
237
237
  }
238
- /** Re-hydrate session from storage. Called by the parent SDK
239
- * during init() after Storage.hydrate() has run. Marks the
240
- * internal ready promise as resolved so queued auth calls
241
- * unblock. */
238
+ /**
239
+ * Re-hydrate session from storage. Called by the parent SDK during
240
+ * init() after Storage.hydrate() has run. Marks the internal ready
241
+ * promise as resolved so queued auth calls unblock.
242
+ *
243
+ * s58.47 — restore the user even when the cached ACCESS token is
244
+ * missing/expired, as long as USER_KEY + REFRESH_KEY are present.
245
+ * Pre-s58.47 this required BOTH USER_KEY and TOKEN_KEY, which
246
+ * caused a cold-start regression: if the access token rotated out
247
+ * of storage (TTL elapsed, app killed between persists, partial
248
+ * write, AsyncStorage eviction) the user appeared signed out even
249
+ * though their refresh chain was still alive in storage. Hosts
250
+ * then called `signInAnonymously()` on every launch and minted a
251
+ * fresh anon user, fragmenting analytics across sessions
252
+ * (Pulse News symptom). With the refresh token present, the next
253
+ * `getAccessToken()` call will silently refresh + restore a valid
254
+ * access token without disturbing identity.
255
+ */
242
256
  hydrate() {
243
257
  const cachedUser = this.hooks.storage.get(USER_KEY);
244
258
  const cachedToken = this.hooks.storage.get(TOKEN_KEY);
259
+ const cachedRefresh = this.hooks.storage.get(REFRESH_KEY);
245
260
  const cachedExpires = this.hooks.storage.get(TOKEN_EXPIRES_KEY);
246
- if (cachedUser && cachedToken) {
261
+ if (cachedUser && (cachedToken || cachedRefresh)) {
247
262
  try {
248
263
  const parsed = JSON.parse(cachedUser);
249
264
  if (typeof parsed.id !== "string" || parsed.id.length === 0) throw new Error("invalid cache");
250
265
  this.user = parsed;
251
- this.accessToken = cachedToken;
252
- this.accessExpiresAt = cachedExpires ? Number(cachedExpires) : 0;
266
+ if (cachedToken) {
267
+ this.accessToken = cachedToken;
268
+ this.accessExpiresAt = cachedExpires ? Number(cachedExpires) : 0;
269
+ } else {
270
+ this.accessToken = null;
271
+ this.accessExpiresAt = 0;
272
+ }
253
273
  this.hooks.onIdentityChange(this.user.id);
254
274
  } catch {
255
275
  this.hooks.storage.remove(USER_KEY);
package/dist/index.d.cts CHANGED
@@ -122,10 +122,24 @@ declare class Auth {
122
122
  private readyPromise;
123
123
  private resolveReady;
124
124
  constructor(hooks: AuthHooks);
125
- /** Re-hydrate session from storage. Called by the parent SDK
126
- * during init() after Storage.hydrate() has run. Marks the
127
- * internal ready promise as resolved so queued auth calls
128
- * unblock. */
125
+ /**
126
+ * Re-hydrate session from storage. Called by the parent SDK during
127
+ * init() after Storage.hydrate() has run. Marks the internal ready
128
+ * promise as resolved so queued auth calls unblock.
129
+ *
130
+ * s58.47 — restore the user even when the cached ACCESS token is
131
+ * missing/expired, as long as USER_KEY + REFRESH_KEY are present.
132
+ * Pre-s58.47 this required BOTH USER_KEY and TOKEN_KEY, which
133
+ * caused a cold-start regression: if the access token rotated out
134
+ * of storage (TTL elapsed, app killed between persists, partial
135
+ * write, AsyncStorage eviction) the user appeared signed out even
136
+ * though their refresh chain was still alive in storage. Hosts
137
+ * then called `signInAnonymously()` on every launch and minted a
138
+ * fresh anon user, fragmenting analytics across sessions
139
+ * (Pulse News symptom). With the refresh token present, the next
140
+ * `getAccessToken()` call will silently refresh + restore a valid
141
+ * access token without disturbing identity.
142
+ */
129
143
  hydrate(): void;
130
144
  getCurrentUser(): AuthUser | null;
131
145
  /**
package/dist/index.d.ts CHANGED
@@ -122,10 +122,24 @@ declare class Auth {
122
122
  private readyPromise;
123
123
  private resolveReady;
124
124
  constructor(hooks: AuthHooks);
125
- /** Re-hydrate session from storage. Called by the parent SDK
126
- * during init() after Storage.hydrate() has run. Marks the
127
- * internal ready promise as resolved so queued auth calls
128
- * unblock. */
125
+ /**
126
+ * Re-hydrate session from storage. Called by the parent SDK during
127
+ * init() after Storage.hydrate() has run. Marks the internal ready
128
+ * promise as resolved so queued auth calls unblock.
129
+ *
130
+ * s58.47 — restore the user even when the cached ACCESS token is
131
+ * missing/expired, as long as USER_KEY + REFRESH_KEY are present.
132
+ * Pre-s58.47 this required BOTH USER_KEY and TOKEN_KEY, which
133
+ * caused a cold-start regression: if the access token rotated out
134
+ * of storage (TTL elapsed, app killed between persists, partial
135
+ * write, AsyncStorage eviction) the user appeared signed out even
136
+ * though their refresh chain was still alive in storage. Hosts
137
+ * then called `signInAnonymously()` on every launch and minted a
138
+ * fresh anon user, fragmenting analytics across sessions
139
+ * (Pulse News symptom). With the refresh token present, the next
140
+ * `getAccessToken()` call will silently refresh + restore a valid
141
+ * access token without disturbing identity.
142
+ */
129
143
  hydrate(): void;
130
144
  getCurrentUser(): AuthUser | null;
131
145
  /**
package/dist/index.js CHANGED
@@ -195,21 +195,41 @@ var Auth = class {
195
195
  this.resolveReady = res;
196
196
  });
197
197
  }
198
- /** Re-hydrate session from storage. Called by the parent SDK
199
- * during init() after Storage.hydrate() has run. Marks the
200
- * internal ready promise as resolved so queued auth calls
201
- * unblock. */
198
+ /**
199
+ * Re-hydrate session from storage. Called by the parent SDK during
200
+ * init() after Storage.hydrate() has run. Marks the internal ready
201
+ * promise as resolved so queued auth calls unblock.
202
+ *
203
+ * s58.47 — restore the user even when the cached ACCESS token is
204
+ * missing/expired, as long as USER_KEY + REFRESH_KEY are present.
205
+ * Pre-s58.47 this required BOTH USER_KEY and TOKEN_KEY, which
206
+ * caused a cold-start regression: if the access token rotated out
207
+ * of storage (TTL elapsed, app killed between persists, partial
208
+ * write, AsyncStorage eviction) the user appeared signed out even
209
+ * though their refresh chain was still alive in storage. Hosts
210
+ * then called `signInAnonymously()` on every launch and minted a
211
+ * fresh anon user, fragmenting analytics across sessions
212
+ * (Pulse News symptom). With the refresh token present, the next
213
+ * `getAccessToken()` call will silently refresh + restore a valid
214
+ * access token without disturbing identity.
215
+ */
202
216
  hydrate() {
203
217
  const cachedUser = this.hooks.storage.get(USER_KEY);
204
218
  const cachedToken = this.hooks.storage.get(TOKEN_KEY);
219
+ const cachedRefresh = this.hooks.storage.get(REFRESH_KEY);
205
220
  const cachedExpires = this.hooks.storage.get(TOKEN_EXPIRES_KEY);
206
- if (cachedUser && cachedToken) {
221
+ if (cachedUser && (cachedToken || cachedRefresh)) {
207
222
  try {
208
223
  const parsed = JSON.parse(cachedUser);
209
224
  if (typeof parsed.id !== "string" || parsed.id.length === 0) throw new Error("invalid cache");
210
225
  this.user = parsed;
211
- this.accessToken = cachedToken;
212
- this.accessExpiresAt = cachedExpires ? Number(cachedExpires) : 0;
226
+ if (cachedToken) {
227
+ this.accessToken = cachedToken;
228
+ this.accessExpiresAt = cachedExpires ? Number(cachedExpires) : 0;
229
+ } else {
230
+ this.accessToken = null;
231
+ this.accessExpiresAt = 0;
232
+ }
213
233
  this.hooks.onIdentityChange(this.user.id);
214
234
  } catch {
215
235
  this.hooks.storage.remove(USER_KEY);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendoracloud/sdk-react-native",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
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",