@mitway/sdk 0.4.0 → 0.5.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 +134 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -2
- package/dist/index.d.ts +52 -2
- package/dist/index.js +134 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -199,6 +199,7 @@ var Logger = class {
|
|
|
199
199
|
|
|
200
200
|
// src/lib/token-manager.ts
|
|
201
201
|
var CSRF_TOKEN_COOKIE = "mitway_baas_csrf_token";
|
|
202
|
+
var DEFAULT_STORAGE_KEY = "mitway_baas_session";
|
|
202
203
|
function getCsrfToken() {
|
|
203
204
|
if (typeof document === "undefined") return null;
|
|
204
205
|
const match = document.cookie.split(";").find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));
|
|
@@ -218,13 +219,24 @@ function clearCsrfToken() {
|
|
|
218
219
|
}
|
|
219
220
|
var TokenManager = class {
|
|
220
221
|
accessToken = null;
|
|
222
|
+
refreshToken = null;
|
|
221
223
|
user = null;
|
|
224
|
+
persistSession;
|
|
225
|
+
storageKey;
|
|
222
226
|
/** Fired when the access token changes (used by long-lived consumers). */
|
|
223
227
|
onTokenChange = null;
|
|
228
|
+
constructor(opts) {
|
|
229
|
+
this.persistSession = opts?.persistSession ?? true;
|
|
230
|
+
this.storageKey = opts?.storageKey ?? DEFAULT_STORAGE_KEY;
|
|
231
|
+
}
|
|
224
232
|
saveSession(session) {
|
|
225
233
|
const tokenChanged = session.accessToken !== this.accessToken;
|
|
226
234
|
this.accessToken = session.accessToken;
|
|
227
235
|
this.user = session.user;
|
|
236
|
+
if (session.refreshToken !== void 0) {
|
|
237
|
+
this.refreshToken = session.refreshToken ?? null;
|
|
238
|
+
}
|
|
239
|
+
this.persist();
|
|
228
240
|
if (tokenChanged && this.onTokenChange) {
|
|
229
241
|
this.onTokenChange();
|
|
230
242
|
}
|
|
@@ -233,6 +245,7 @@ var TokenManager = class {
|
|
|
233
245
|
if (!this.accessToken || !this.user) return null;
|
|
234
246
|
return {
|
|
235
247
|
accessToken: this.accessToken,
|
|
248
|
+
refreshToken: this.refreshToken ?? void 0,
|
|
236
249
|
user: this.user
|
|
237
250
|
};
|
|
238
251
|
}
|
|
@@ -242,24 +255,76 @@ var TokenManager = class {
|
|
|
242
255
|
setAccessToken(token) {
|
|
243
256
|
const tokenChanged = token !== this.accessToken;
|
|
244
257
|
this.accessToken = token;
|
|
258
|
+
this.persist();
|
|
245
259
|
if (tokenChanged && this.onTokenChange) {
|
|
246
260
|
this.onTokenChange();
|
|
247
261
|
}
|
|
248
262
|
}
|
|
263
|
+
getRefreshToken() {
|
|
264
|
+
return this.refreshToken;
|
|
265
|
+
}
|
|
266
|
+
setRefreshToken(token) {
|
|
267
|
+
this.refreshToken = token;
|
|
268
|
+
this.persist();
|
|
269
|
+
}
|
|
249
270
|
getUser() {
|
|
250
271
|
return this.user;
|
|
251
272
|
}
|
|
252
273
|
setUser(user) {
|
|
253
274
|
this.user = user;
|
|
275
|
+
this.persist();
|
|
254
276
|
}
|
|
255
277
|
clearSession() {
|
|
256
278
|
const hadToken = this.accessToken !== null;
|
|
257
279
|
this.accessToken = null;
|
|
280
|
+
this.refreshToken = null;
|
|
258
281
|
this.user = null;
|
|
282
|
+
this.removePersisted();
|
|
259
283
|
if (hadToken && this.onTokenChange) {
|
|
260
284
|
this.onTokenChange();
|
|
261
285
|
}
|
|
262
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Restore the session from localStorage. Returns true if a persisted
|
|
289
|
+
* session was found and loaded into memory.
|
|
290
|
+
*/
|
|
291
|
+
restoreSession() {
|
|
292
|
+
if (!this.persistSession || typeof localStorage === "undefined") return false;
|
|
293
|
+
try {
|
|
294
|
+
const raw = localStorage.getItem(this.storageKey);
|
|
295
|
+
if (!raw) return false;
|
|
296
|
+
const stored = JSON.parse(raw);
|
|
297
|
+
if (!stored.accessToken || !stored.user) return false;
|
|
298
|
+
this.accessToken = stored.accessToken;
|
|
299
|
+
this.refreshToken = stored.refreshToken ?? null;
|
|
300
|
+
this.user = stored.user;
|
|
301
|
+
return true;
|
|
302
|
+
} catch {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
persist() {
|
|
307
|
+
if (!this.persistSession || typeof localStorage === "undefined") return;
|
|
308
|
+
if (!this.accessToken || !this.user) return;
|
|
309
|
+
try {
|
|
310
|
+
const data = {
|
|
311
|
+
accessToken: this.accessToken,
|
|
312
|
+
user: this.user
|
|
313
|
+
};
|
|
314
|
+
if (this.refreshToken) {
|
|
315
|
+
data.refreshToken = this.refreshToken;
|
|
316
|
+
}
|
|
317
|
+
localStorage.setItem(this.storageKey, JSON.stringify(data));
|
|
318
|
+
} catch {
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
removePersisted() {
|
|
322
|
+
if (!this.persistSession || typeof localStorage === "undefined") return;
|
|
323
|
+
try {
|
|
324
|
+
localStorage.removeItem(this.storageKey);
|
|
325
|
+
} catch {
|
|
326
|
+
}
|
|
327
|
+
}
|
|
263
328
|
};
|
|
264
329
|
|
|
265
330
|
// src/lib/auth-envelope.ts
|
|
@@ -679,6 +744,7 @@ var Auth = class {
|
|
|
679
744
|
saveSessionFromResponse(response) {
|
|
680
745
|
const session = {
|
|
681
746
|
accessToken: response.accessToken,
|
|
747
|
+
refreshToken: response.refreshToken,
|
|
682
748
|
user: response.user
|
|
683
749
|
};
|
|
684
750
|
if (response.csrfToken) {
|
|
@@ -772,6 +838,70 @@ var Auth = class {
|
|
|
772
838
|
return wrapError(error, "Session refresh failed");
|
|
773
839
|
}
|
|
774
840
|
}
|
|
841
|
+
/**
|
|
842
|
+
* Restore the session from localStorage and validate it with the backend.
|
|
843
|
+
* Call this once on app startup (e.g. in a React AuthProvider useEffect).
|
|
844
|
+
*
|
|
845
|
+
* Flow:
|
|
846
|
+
* 1. Read persisted session from localStorage.
|
|
847
|
+
* 2. Populate in-memory state (TokenManager + HttpClient).
|
|
848
|
+
* 3. Validate with `GET /api/auth/sessions/current`.
|
|
849
|
+
* - If the access token expired, the HttpClient auto-refresh kicks in
|
|
850
|
+
* using the persisted refresh token (sent in the POST body, not
|
|
851
|
+
* cookies — works cross-site).
|
|
852
|
+
* 4. Return the validated user or an error.
|
|
853
|
+
*
|
|
854
|
+
* If no persisted session exists, returns `{ data: null, error }` — the
|
|
855
|
+
* app should show the login page.
|
|
856
|
+
*/
|
|
857
|
+
async initialize() {
|
|
858
|
+
const restored = this.tokenManager.restoreSession();
|
|
859
|
+
if (!restored) {
|
|
860
|
+
return {
|
|
861
|
+
data: null,
|
|
862
|
+
error: new MitwayBaasError("No persisted session", 0, "NO_SESSION")
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
const session = this.tokenManager.getSession();
|
|
866
|
+
if (!session) {
|
|
867
|
+
return {
|
|
868
|
+
data: null,
|
|
869
|
+
error: new MitwayBaasError("No persisted session", 0, "NO_SESSION")
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
this.http.setAuthToken(session.accessToken);
|
|
873
|
+
const refreshToken = this.tokenManager.getRefreshToken();
|
|
874
|
+
if (refreshToken) {
|
|
875
|
+
this.http.setRefreshToken(refreshToken);
|
|
876
|
+
}
|
|
877
|
+
try {
|
|
878
|
+
const response = await this.http.get(
|
|
879
|
+
"/api/auth/sessions/current"
|
|
880
|
+
);
|
|
881
|
+
if (response?.user) {
|
|
882
|
+
this.tokenManager.setUser(response.user);
|
|
883
|
+
return {
|
|
884
|
+
data: {
|
|
885
|
+
user: response.user,
|
|
886
|
+
accessToken: session.accessToken
|
|
887
|
+
},
|
|
888
|
+
error: null
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
this.tokenManager.clearSession();
|
|
892
|
+
this.http.setAuthToken(null);
|
|
893
|
+
this.http.setRefreshToken(null);
|
|
894
|
+
return {
|
|
895
|
+
data: null,
|
|
896
|
+
error: new MitwayBaasError("Invalid session", 401, "INVALID_SESSION")
|
|
897
|
+
};
|
|
898
|
+
} catch (error) {
|
|
899
|
+
this.tokenManager.clearSession();
|
|
900
|
+
this.http.setAuthToken(null);
|
|
901
|
+
this.http.setRefreshToken(null);
|
|
902
|
+
return wrapError(error, "Session restore failed");
|
|
903
|
+
}
|
|
904
|
+
}
|
|
775
905
|
/**
|
|
776
906
|
* Get the current in-memory session, or null if the user is not signed in.
|
|
777
907
|
* Synchronous — does not hit the network.
|
|
@@ -1915,7 +2045,10 @@ var MitwayBaasClient = class {
|
|
|
1915
2045
|
storage;
|
|
1916
2046
|
constructor(config = {}) {
|
|
1917
2047
|
const logger = new Logger(config.debug);
|
|
1918
|
-
this.tokenManager = new TokenManager(
|
|
2048
|
+
this.tokenManager = new TokenManager({
|
|
2049
|
+
persistSession: config.persistSession,
|
|
2050
|
+
storageKey: config.storageKey
|
|
2051
|
+
});
|
|
1919
2052
|
this.http = new HttpClient(config, this.tokenManager, logger);
|
|
1920
2053
|
this.auth = new Auth(this.http, this.tokenManager);
|
|
1921
2054
|
this.database = new Database(this.http, this.tokenManager, config.anonKey);
|