@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.d.cts
CHANGED
|
@@ -33,22 +33,42 @@ interface User {
|
|
|
33
33
|
/**
|
|
34
34
|
* Token Manager for the MITWAY-BaaS SDK.
|
|
35
35
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
36
|
+
* Stores the access token + user in memory and optionally persists them
|
|
37
|
+
* to `localStorage` so sessions survive page reloads (F5). Browser CSRF
|
|
38
|
+
* token lives in a cookie for the cookie-based refresh flow.
|
|
38
39
|
*/
|
|
39
40
|
|
|
41
|
+
interface TokenManagerOptions {
|
|
42
|
+
/** Persist session to localStorage so it survives page reloads. Default: true. */
|
|
43
|
+
persistSession?: boolean;
|
|
44
|
+
/** localStorage key. Default: 'mitway_baas_session'. */
|
|
45
|
+
storageKey?: string;
|
|
46
|
+
}
|
|
40
47
|
declare class TokenManager {
|
|
41
48
|
private accessToken;
|
|
49
|
+
private refreshToken;
|
|
42
50
|
private user;
|
|
51
|
+
private readonly persistSession;
|
|
52
|
+
private readonly storageKey;
|
|
43
53
|
/** Fired when the access token changes (used by long-lived consumers). */
|
|
44
54
|
onTokenChange: (() => void) | null;
|
|
55
|
+
constructor(opts?: TokenManagerOptions);
|
|
45
56
|
saveSession(session: AuthSession): void;
|
|
46
57
|
getSession(): AuthSession | null;
|
|
47
58
|
getAccessToken(): string | null;
|
|
48
59
|
setAccessToken(token: string): void;
|
|
60
|
+
getRefreshToken(): string | null;
|
|
61
|
+
setRefreshToken(token: string | null): void;
|
|
49
62
|
getUser(): User | null;
|
|
50
63
|
setUser(user: User): void;
|
|
51
64
|
clearSession(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Restore the session from localStorage. Returns true if a persisted
|
|
67
|
+
* session was found and loaded into memory.
|
|
68
|
+
*/
|
|
69
|
+
restoreSession(): boolean;
|
|
70
|
+
private persist;
|
|
71
|
+
private removePersisted;
|
|
52
72
|
}
|
|
53
73
|
|
|
54
74
|
/**
|
|
@@ -451,6 +471,18 @@ interface MitwayBaasConfig {
|
|
|
451
471
|
* Realtime transport options. See `RealtimeOptions`.
|
|
452
472
|
*/
|
|
453
473
|
realtime?: RealtimeOptions;
|
|
474
|
+
/**
|
|
475
|
+
* Persist the auth session to `localStorage` so it survives page reloads.
|
|
476
|
+
* Set to `false` for SSR / Node.js environments where `localStorage` is
|
|
477
|
+
* not available.
|
|
478
|
+
* @default true
|
|
479
|
+
*/
|
|
480
|
+
persistSession?: boolean;
|
|
481
|
+
/**
|
|
482
|
+
* `localStorage` key used to persist the session.
|
|
483
|
+
* @default "mitway_baas_session"
|
|
484
|
+
*/
|
|
485
|
+
storageKey?: string;
|
|
454
486
|
}
|
|
455
487
|
/**
|
|
456
488
|
* Active user session in memory. Mirrors what the auth endpoints return.
|
|
@@ -458,6 +490,7 @@ interface MitwayBaasConfig {
|
|
|
458
490
|
interface AuthSession {
|
|
459
491
|
user: User;
|
|
460
492
|
accessToken: string;
|
|
493
|
+
refreshToken?: string;
|
|
461
494
|
expiresAt?: Date;
|
|
462
495
|
}
|
|
463
496
|
/**
|
|
@@ -654,6 +687,23 @@ declare class Auth {
|
|
|
654
687
|
* not need to call it directly.
|
|
655
688
|
*/
|
|
656
689
|
refreshSession(): Promise<AuthResult<AuthResponse>>;
|
|
690
|
+
/**
|
|
691
|
+
* Restore the session from localStorage and validate it with the backend.
|
|
692
|
+
* Call this once on app startup (e.g. in a React AuthProvider useEffect).
|
|
693
|
+
*
|
|
694
|
+
* Flow:
|
|
695
|
+
* 1. Read persisted session from localStorage.
|
|
696
|
+
* 2. Populate in-memory state (TokenManager + HttpClient).
|
|
697
|
+
* 3. Validate with `GET /api/auth/sessions/current`.
|
|
698
|
+
* - If the access token expired, the HttpClient auto-refresh kicks in
|
|
699
|
+
* using the persisted refresh token (sent in the POST body, not
|
|
700
|
+
* cookies — works cross-site).
|
|
701
|
+
* 4. Return the validated user or an error.
|
|
702
|
+
*
|
|
703
|
+
* If no persisted session exists, returns `{ data: null, error }` — the
|
|
704
|
+
* app should show the login page.
|
|
705
|
+
*/
|
|
706
|
+
initialize(): Promise<AuthResult<AuthResponse>>;
|
|
657
707
|
/**
|
|
658
708
|
* Get the current in-memory session, or null if the user is not signed in.
|
|
659
709
|
* Synchronous — does not hit the network.
|
package/dist/index.d.ts
CHANGED
|
@@ -33,22 +33,42 @@ interface User {
|
|
|
33
33
|
/**
|
|
34
34
|
* Token Manager for the MITWAY-BaaS SDK.
|
|
35
35
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
36
|
+
* Stores the access token + user in memory and optionally persists them
|
|
37
|
+
* to `localStorage` so sessions survive page reloads (F5). Browser CSRF
|
|
38
|
+
* token lives in a cookie for the cookie-based refresh flow.
|
|
38
39
|
*/
|
|
39
40
|
|
|
41
|
+
interface TokenManagerOptions {
|
|
42
|
+
/** Persist session to localStorage so it survives page reloads. Default: true. */
|
|
43
|
+
persistSession?: boolean;
|
|
44
|
+
/** localStorage key. Default: 'mitway_baas_session'. */
|
|
45
|
+
storageKey?: string;
|
|
46
|
+
}
|
|
40
47
|
declare class TokenManager {
|
|
41
48
|
private accessToken;
|
|
49
|
+
private refreshToken;
|
|
42
50
|
private user;
|
|
51
|
+
private readonly persistSession;
|
|
52
|
+
private readonly storageKey;
|
|
43
53
|
/** Fired when the access token changes (used by long-lived consumers). */
|
|
44
54
|
onTokenChange: (() => void) | null;
|
|
55
|
+
constructor(opts?: TokenManagerOptions);
|
|
45
56
|
saveSession(session: AuthSession): void;
|
|
46
57
|
getSession(): AuthSession | null;
|
|
47
58
|
getAccessToken(): string | null;
|
|
48
59
|
setAccessToken(token: string): void;
|
|
60
|
+
getRefreshToken(): string | null;
|
|
61
|
+
setRefreshToken(token: string | null): void;
|
|
49
62
|
getUser(): User | null;
|
|
50
63
|
setUser(user: User): void;
|
|
51
64
|
clearSession(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Restore the session from localStorage. Returns true if a persisted
|
|
67
|
+
* session was found and loaded into memory.
|
|
68
|
+
*/
|
|
69
|
+
restoreSession(): boolean;
|
|
70
|
+
private persist;
|
|
71
|
+
private removePersisted;
|
|
52
72
|
}
|
|
53
73
|
|
|
54
74
|
/**
|
|
@@ -451,6 +471,18 @@ interface MitwayBaasConfig {
|
|
|
451
471
|
* Realtime transport options. See `RealtimeOptions`.
|
|
452
472
|
*/
|
|
453
473
|
realtime?: RealtimeOptions;
|
|
474
|
+
/**
|
|
475
|
+
* Persist the auth session to `localStorage` so it survives page reloads.
|
|
476
|
+
* Set to `false` for SSR / Node.js environments where `localStorage` is
|
|
477
|
+
* not available.
|
|
478
|
+
* @default true
|
|
479
|
+
*/
|
|
480
|
+
persistSession?: boolean;
|
|
481
|
+
/**
|
|
482
|
+
* `localStorage` key used to persist the session.
|
|
483
|
+
* @default "mitway_baas_session"
|
|
484
|
+
*/
|
|
485
|
+
storageKey?: string;
|
|
454
486
|
}
|
|
455
487
|
/**
|
|
456
488
|
* Active user session in memory. Mirrors what the auth endpoints return.
|
|
@@ -458,6 +490,7 @@ interface MitwayBaasConfig {
|
|
|
458
490
|
interface AuthSession {
|
|
459
491
|
user: User;
|
|
460
492
|
accessToken: string;
|
|
493
|
+
refreshToken?: string;
|
|
461
494
|
expiresAt?: Date;
|
|
462
495
|
}
|
|
463
496
|
/**
|
|
@@ -654,6 +687,23 @@ declare class Auth {
|
|
|
654
687
|
* not need to call it directly.
|
|
655
688
|
*/
|
|
656
689
|
refreshSession(): Promise<AuthResult<AuthResponse>>;
|
|
690
|
+
/**
|
|
691
|
+
* Restore the session from localStorage and validate it with the backend.
|
|
692
|
+
* Call this once on app startup (e.g. in a React AuthProvider useEffect).
|
|
693
|
+
*
|
|
694
|
+
* Flow:
|
|
695
|
+
* 1. Read persisted session from localStorage.
|
|
696
|
+
* 2. Populate in-memory state (TokenManager + HttpClient).
|
|
697
|
+
* 3. Validate with `GET /api/auth/sessions/current`.
|
|
698
|
+
* - If the access token expired, the HttpClient auto-refresh kicks in
|
|
699
|
+
* using the persisted refresh token (sent in the POST body, not
|
|
700
|
+
* cookies — works cross-site).
|
|
701
|
+
* 4. Return the validated user or an error.
|
|
702
|
+
*
|
|
703
|
+
* If no persisted session exists, returns `{ data: null, error }` — the
|
|
704
|
+
* app should show the login page.
|
|
705
|
+
*/
|
|
706
|
+
initialize(): Promise<AuthResult<AuthResponse>>;
|
|
657
707
|
/**
|
|
658
708
|
* Get the current in-memory session, or null if the user is not signed in.
|
|
659
709
|
* Synchronous — does not hit the network.
|
package/dist/index.js
CHANGED
|
@@ -161,6 +161,7 @@ var Logger = class {
|
|
|
161
161
|
|
|
162
162
|
// src/lib/token-manager.ts
|
|
163
163
|
var CSRF_TOKEN_COOKIE = "mitway_baas_csrf_token";
|
|
164
|
+
var DEFAULT_STORAGE_KEY = "mitway_baas_session";
|
|
164
165
|
function getCsrfToken() {
|
|
165
166
|
if (typeof document === "undefined") return null;
|
|
166
167
|
const match = document.cookie.split(";").find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));
|
|
@@ -180,13 +181,24 @@ function clearCsrfToken() {
|
|
|
180
181
|
}
|
|
181
182
|
var TokenManager = class {
|
|
182
183
|
accessToken = null;
|
|
184
|
+
refreshToken = null;
|
|
183
185
|
user = null;
|
|
186
|
+
persistSession;
|
|
187
|
+
storageKey;
|
|
184
188
|
/** Fired when the access token changes (used by long-lived consumers). */
|
|
185
189
|
onTokenChange = null;
|
|
190
|
+
constructor(opts) {
|
|
191
|
+
this.persistSession = opts?.persistSession ?? true;
|
|
192
|
+
this.storageKey = opts?.storageKey ?? DEFAULT_STORAGE_KEY;
|
|
193
|
+
}
|
|
186
194
|
saveSession(session) {
|
|
187
195
|
const tokenChanged = session.accessToken !== this.accessToken;
|
|
188
196
|
this.accessToken = session.accessToken;
|
|
189
197
|
this.user = session.user;
|
|
198
|
+
if (session.refreshToken !== void 0) {
|
|
199
|
+
this.refreshToken = session.refreshToken ?? null;
|
|
200
|
+
}
|
|
201
|
+
this.persist();
|
|
190
202
|
if (tokenChanged && this.onTokenChange) {
|
|
191
203
|
this.onTokenChange();
|
|
192
204
|
}
|
|
@@ -195,6 +207,7 @@ var TokenManager = class {
|
|
|
195
207
|
if (!this.accessToken || !this.user) return null;
|
|
196
208
|
return {
|
|
197
209
|
accessToken: this.accessToken,
|
|
210
|
+
refreshToken: this.refreshToken ?? void 0,
|
|
198
211
|
user: this.user
|
|
199
212
|
};
|
|
200
213
|
}
|
|
@@ -204,24 +217,76 @@ var TokenManager = class {
|
|
|
204
217
|
setAccessToken(token) {
|
|
205
218
|
const tokenChanged = token !== this.accessToken;
|
|
206
219
|
this.accessToken = token;
|
|
220
|
+
this.persist();
|
|
207
221
|
if (tokenChanged && this.onTokenChange) {
|
|
208
222
|
this.onTokenChange();
|
|
209
223
|
}
|
|
210
224
|
}
|
|
225
|
+
getRefreshToken() {
|
|
226
|
+
return this.refreshToken;
|
|
227
|
+
}
|
|
228
|
+
setRefreshToken(token) {
|
|
229
|
+
this.refreshToken = token;
|
|
230
|
+
this.persist();
|
|
231
|
+
}
|
|
211
232
|
getUser() {
|
|
212
233
|
return this.user;
|
|
213
234
|
}
|
|
214
235
|
setUser(user) {
|
|
215
236
|
this.user = user;
|
|
237
|
+
this.persist();
|
|
216
238
|
}
|
|
217
239
|
clearSession() {
|
|
218
240
|
const hadToken = this.accessToken !== null;
|
|
219
241
|
this.accessToken = null;
|
|
242
|
+
this.refreshToken = null;
|
|
220
243
|
this.user = null;
|
|
244
|
+
this.removePersisted();
|
|
221
245
|
if (hadToken && this.onTokenChange) {
|
|
222
246
|
this.onTokenChange();
|
|
223
247
|
}
|
|
224
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Restore the session from localStorage. Returns true if a persisted
|
|
251
|
+
* session was found and loaded into memory.
|
|
252
|
+
*/
|
|
253
|
+
restoreSession() {
|
|
254
|
+
if (!this.persistSession || typeof localStorage === "undefined") return false;
|
|
255
|
+
try {
|
|
256
|
+
const raw = localStorage.getItem(this.storageKey);
|
|
257
|
+
if (!raw) return false;
|
|
258
|
+
const stored = JSON.parse(raw);
|
|
259
|
+
if (!stored.accessToken || !stored.user) return false;
|
|
260
|
+
this.accessToken = stored.accessToken;
|
|
261
|
+
this.refreshToken = stored.refreshToken ?? null;
|
|
262
|
+
this.user = stored.user;
|
|
263
|
+
return true;
|
|
264
|
+
} catch {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
persist() {
|
|
269
|
+
if (!this.persistSession || typeof localStorage === "undefined") return;
|
|
270
|
+
if (!this.accessToken || !this.user) return;
|
|
271
|
+
try {
|
|
272
|
+
const data = {
|
|
273
|
+
accessToken: this.accessToken,
|
|
274
|
+
user: this.user
|
|
275
|
+
};
|
|
276
|
+
if (this.refreshToken) {
|
|
277
|
+
data.refreshToken = this.refreshToken;
|
|
278
|
+
}
|
|
279
|
+
localStorage.setItem(this.storageKey, JSON.stringify(data));
|
|
280
|
+
} catch {
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
removePersisted() {
|
|
284
|
+
if (!this.persistSession || typeof localStorage === "undefined") return;
|
|
285
|
+
try {
|
|
286
|
+
localStorage.removeItem(this.storageKey);
|
|
287
|
+
} catch {
|
|
288
|
+
}
|
|
289
|
+
}
|
|
225
290
|
};
|
|
226
291
|
|
|
227
292
|
// src/lib/auth-envelope.ts
|
|
@@ -641,6 +706,7 @@ var Auth = class {
|
|
|
641
706
|
saveSessionFromResponse(response) {
|
|
642
707
|
const session = {
|
|
643
708
|
accessToken: response.accessToken,
|
|
709
|
+
refreshToken: response.refreshToken,
|
|
644
710
|
user: response.user
|
|
645
711
|
};
|
|
646
712
|
if (response.csrfToken) {
|
|
@@ -734,6 +800,70 @@ var Auth = class {
|
|
|
734
800
|
return wrapError(error, "Session refresh failed");
|
|
735
801
|
}
|
|
736
802
|
}
|
|
803
|
+
/**
|
|
804
|
+
* Restore the session from localStorage and validate it with the backend.
|
|
805
|
+
* Call this once on app startup (e.g. in a React AuthProvider useEffect).
|
|
806
|
+
*
|
|
807
|
+
* Flow:
|
|
808
|
+
* 1. Read persisted session from localStorage.
|
|
809
|
+
* 2. Populate in-memory state (TokenManager + HttpClient).
|
|
810
|
+
* 3. Validate with `GET /api/auth/sessions/current`.
|
|
811
|
+
* - If the access token expired, the HttpClient auto-refresh kicks in
|
|
812
|
+
* using the persisted refresh token (sent in the POST body, not
|
|
813
|
+
* cookies — works cross-site).
|
|
814
|
+
* 4. Return the validated user or an error.
|
|
815
|
+
*
|
|
816
|
+
* If no persisted session exists, returns `{ data: null, error }` — the
|
|
817
|
+
* app should show the login page.
|
|
818
|
+
*/
|
|
819
|
+
async initialize() {
|
|
820
|
+
const restored = this.tokenManager.restoreSession();
|
|
821
|
+
if (!restored) {
|
|
822
|
+
return {
|
|
823
|
+
data: null,
|
|
824
|
+
error: new MitwayBaasError("No persisted session", 0, "NO_SESSION")
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
const session = this.tokenManager.getSession();
|
|
828
|
+
if (!session) {
|
|
829
|
+
return {
|
|
830
|
+
data: null,
|
|
831
|
+
error: new MitwayBaasError("No persisted session", 0, "NO_SESSION")
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
this.http.setAuthToken(session.accessToken);
|
|
835
|
+
const refreshToken = this.tokenManager.getRefreshToken();
|
|
836
|
+
if (refreshToken) {
|
|
837
|
+
this.http.setRefreshToken(refreshToken);
|
|
838
|
+
}
|
|
839
|
+
try {
|
|
840
|
+
const response = await this.http.get(
|
|
841
|
+
"/api/auth/sessions/current"
|
|
842
|
+
);
|
|
843
|
+
if (response?.user) {
|
|
844
|
+
this.tokenManager.setUser(response.user);
|
|
845
|
+
return {
|
|
846
|
+
data: {
|
|
847
|
+
user: response.user,
|
|
848
|
+
accessToken: session.accessToken
|
|
849
|
+
},
|
|
850
|
+
error: null
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
this.tokenManager.clearSession();
|
|
854
|
+
this.http.setAuthToken(null);
|
|
855
|
+
this.http.setRefreshToken(null);
|
|
856
|
+
return {
|
|
857
|
+
data: null,
|
|
858
|
+
error: new MitwayBaasError("Invalid session", 401, "INVALID_SESSION")
|
|
859
|
+
};
|
|
860
|
+
} catch (error) {
|
|
861
|
+
this.tokenManager.clearSession();
|
|
862
|
+
this.http.setAuthToken(null);
|
|
863
|
+
this.http.setRefreshToken(null);
|
|
864
|
+
return wrapError(error, "Session restore failed");
|
|
865
|
+
}
|
|
866
|
+
}
|
|
737
867
|
/**
|
|
738
868
|
* Get the current in-memory session, or null if the user is not signed in.
|
|
739
869
|
* Synchronous — does not hit the network.
|
|
@@ -1877,7 +2007,10 @@ var MitwayBaasClient = class {
|
|
|
1877
2007
|
storage;
|
|
1878
2008
|
constructor(config = {}) {
|
|
1879
2009
|
const logger = new Logger(config.debug);
|
|
1880
|
-
this.tokenManager = new TokenManager(
|
|
2010
|
+
this.tokenManager = new TokenManager({
|
|
2011
|
+
persistSession: config.persistSession,
|
|
2012
|
+
storageKey: config.storageKey
|
|
2013
|
+
});
|
|
1881
2014
|
this.http = new HttpClient(config, this.tokenManager, logger);
|
|
1882
2015
|
this.auth = new Auth(this.http, this.tokenManager);
|
|
1883
2016
|
this.database = new Database(this.http, this.tokenManager, config.anonKey);
|