@classic-homes/auth 1.8.0 → 1.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/README.md +28 -0
- package/dist/auth.svelte-AIRJEWTG.js +3 -0
- package/dist/{chunk-QTX7L4QY.js → chunk-2IEYKV42.js} +4 -4
- package/dist/{chunk-HVOZBQIF.js → chunk-4SLNFY2N.js} +113 -123
- package/dist/{chunk-X7KH4DDN.js → chunk-PYCXNOMA.js} +3 -1
- package/dist/{chunk-UGD4PNYI.js → chunk-VLDCDFEN.js} +3 -3
- package/dist/{chunk-EBTCVIUQ.js → chunk-XWJ54R6J.js} +2 -2
- package/dist/core/index.d.ts +68 -14
- package/dist/core/index.js +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -5
- package/dist/svelte/index.d.ts +4 -4
- package/dist/svelte/index.js +5 -5
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/{types-C6MqT3DB.d.ts → types-Bqh2gkvu.d.ts} +6 -0
- package/dist/{user-utils-Dla77tvM.d.ts → user-utils-92PeSjcw.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/auth.svelte-FIHKI5BD.js +0 -3
package/README.md
CHANGED
|
@@ -270,6 +270,34 @@ Two server rules to design around:
|
|
|
270
270
|
- The server refuses to remove a user's **last** role, or to grant a role at or
|
|
271
271
|
above the acting user's own level. Both come back as errors.
|
|
272
272
|
|
|
273
|
+
## Token refresh
|
|
274
|
+
|
|
275
|
+
Access tokens are short-lived and refresh tokens rotate (single-use), so a
|
|
276
|
+
refresh must never run twice for the same token. `refreshSession()` is the one
|
|
277
|
+
refresh path — the client's own 401 retry uses it, and so should any code that
|
|
278
|
+
refreshes proactively:
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
import { refreshSession } from '@classic-homes/auth/core';
|
|
282
|
+
|
|
283
|
+
// Before a route guard reads claims (roles/permissions live in the JWT):
|
|
284
|
+
const outcome = await refreshSession({ onlyIfExpired: true });
|
|
285
|
+
// 'fresh' — token still valid, nothing sent
|
|
286
|
+
// 'refreshed' — tokens stored and the Svelte store already updated
|
|
287
|
+
// 'rejected' — session cleared (handleSessionExpired/onSessionExpired/onLogout ran)
|
|
288
|
+
// 'unavailable' — server unreachable/5xx even after retries; session kept, try later
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Guarantees: single-flight per tab (concurrent callers share one call),
|
|
292
|
+
serialized across tabs with a Web Lock and reconciled if another tab rotated
|
|
293
|
+
first, and transient failures retried with `refreshRetryDelays` backoff
|
|
294
|
+
(default `[1000, 3000]`). Do not call `authApi.refreshToken` + `updateStoredTokens`
|
|
295
|
+
yourself for this — that bypasses all of the above and can orphan a rotated
|
|
296
|
+
token.
|
|
297
|
+
|
|
298
|
+
Call `initCrossTabSync()` once at app start so a refresh or sign-out in another
|
|
299
|
+
tab rehydrates this tab's Svelte store.
|
|
300
|
+
|
|
273
301
|
## API Reference
|
|
274
302
|
|
|
275
303
|
### Core Exports
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { authApi } from './chunk-
|
|
2
|
-
import { getUserRoles, hasAnyRole } from './chunk-
|
|
1
|
+
import { authApi } from './chunk-4SLNFY2N.js';
|
|
2
|
+
import { getUserRoles, hasAnyRole } from './chunk-PYCXNOMA.js';
|
|
3
3
|
|
|
4
4
|
// src/core/guards.ts
|
|
5
5
|
function isMfaChallengeResponse(response) {
|
|
@@ -59,7 +59,7 @@ var AuthService = class {
|
|
|
59
59
|
}
|
|
60
60
|
if (options?.autoSetAuth !== false && !isMfaChallengeResponse(response)) {
|
|
61
61
|
try {
|
|
62
|
-
const { authStore } = await import('./auth.svelte-
|
|
62
|
+
const { authStore } = await import('./auth.svelte-AIRJEWTG.js');
|
|
63
63
|
authStore.setAuth(
|
|
64
64
|
response.accessToken,
|
|
65
65
|
response.refreshToken,
|
|
@@ -245,7 +245,7 @@ var AuthService = class {
|
|
|
245
245
|
}
|
|
246
246
|
if (options?.autoSetAuth !== false) {
|
|
247
247
|
try {
|
|
248
|
-
const { authStore } = await import('./auth.svelte-
|
|
248
|
+
const { authStore } = await import('./auth.svelte-AIRJEWTG.js');
|
|
249
249
|
authStore.setAuth(
|
|
250
250
|
response.accessToken,
|
|
251
251
|
response.refreshToken,
|
|
@@ -1,36 +1,9 @@
|
|
|
1
|
-
import { getConfig, getStorage, getFetch, isValidRedirectUrl } from './chunk-
|
|
1
|
+
import { getConfig, getStorage, isTokenExpired, getFetch, isValidRedirectUrl } from './chunk-PYCXNOMA.js';
|
|
2
2
|
|
|
3
3
|
// src/core/client.ts
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
function subscribeTokenRefresh(cb) {
|
|
8
|
-
if (refreshSubscribers.length >= MAX_REFRESH_SUBSCRIBERS) {
|
|
9
|
-
throw new Error("Too many concurrent requests waiting for token refresh. Please try again.");
|
|
10
|
-
}
|
|
11
|
-
refreshSubscribers.push(cb);
|
|
12
|
-
return () => {
|
|
13
|
-
const idx = refreshSubscribers.indexOf(cb);
|
|
14
|
-
if (idx > -1) refreshSubscribers.splice(idx, 1);
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
function flushRefreshSubscribers(token, terminal = false) {
|
|
18
|
-
const subs = refreshSubscribers;
|
|
19
|
-
refreshSubscribers = [];
|
|
20
|
-
subs.forEach((cb) => {
|
|
21
|
-
try {
|
|
22
|
-
cb(token, terminal);
|
|
23
|
-
} catch (e) {
|
|
24
|
-
console.error("Token refresh subscriber error:", e);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
function onTokenRefreshed(token) {
|
|
29
|
-
flushRefreshSubscribers(token);
|
|
30
|
-
}
|
|
31
|
-
function onTokenRefreshFailed(terminal) {
|
|
32
|
-
flushRefreshSubscribers(null, terminal);
|
|
33
|
-
}
|
|
4
|
+
var DEFAULT_REFRESH_RETRY_DELAYS = [1e3, 3e3];
|
|
5
|
+
var refreshInflight = null;
|
|
6
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
34
7
|
function getAccessToken() {
|
|
35
8
|
const config = getConfig();
|
|
36
9
|
const storage = getStorage();
|
|
@@ -65,6 +38,9 @@ function getSessionToken() {
|
|
|
65
38
|
return storage.getItem(getSessionTokenKey());
|
|
66
39
|
}
|
|
67
40
|
function updateStoredTokens(accessToken, refreshToken) {
|
|
41
|
+
void writeStoredTokens(accessToken, refreshToken);
|
|
42
|
+
}
|
|
43
|
+
function writeStoredTokens(accessToken, refreshToken) {
|
|
68
44
|
const config = getConfig();
|
|
69
45
|
const storage = getStorage();
|
|
70
46
|
const storageKey = config.storageKey ?? "classic_auth";
|
|
@@ -77,11 +53,15 @@ function updateStoredTokens(accessToken, refreshToken) {
|
|
|
77
53
|
parsed.accessToken = accessToken;
|
|
78
54
|
parsed.refreshToken = refreshToken;
|
|
79
55
|
storage.setItem(storageKey, JSON.stringify(parsed));
|
|
80
|
-
import('./auth.svelte-FIHKI5BD.js').then(({ authStore }) => {
|
|
81
|
-
authStore.updateTokens(accessToken, refreshToken);
|
|
82
|
-
}).catch(() => {
|
|
83
|
-
});
|
|
84
56
|
config.onTokenRefresh?.({ accessToken, refreshToken });
|
|
57
|
+
return syncSvelteStore((authStore) => authStore.updateTokens(accessToken, refreshToken));
|
|
58
|
+
}
|
|
59
|
+
async function syncSvelteStore(apply) {
|
|
60
|
+
try {
|
|
61
|
+
const { authStore } = await import('./auth.svelte-AIRJEWTG.js');
|
|
62
|
+
apply(authStore);
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
85
65
|
}
|
|
86
66
|
function clearStoredAuth() {
|
|
87
67
|
const config = getConfig();
|
|
@@ -91,20 +71,12 @@ function clearStoredAuth() {
|
|
|
91
71
|
}
|
|
92
72
|
async function expireSession() {
|
|
93
73
|
clearStoredAuth();
|
|
94
|
-
|
|
95
|
-
const { authStore } = await import('./auth.svelte-FIHKI5BD.js');
|
|
96
|
-
authStore.handleSessionExpired();
|
|
97
|
-
} catch {
|
|
98
|
-
}
|
|
74
|
+
await syncSvelteStore((authStore) => authStore.handleSessionExpired());
|
|
99
75
|
getConfig().onLogout?.();
|
|
100
76
|
}
|
|
101
|
-
async function
|
|
102
|
-
const refreshToken = getRefreshToken();
|
|
77
|
+
async function refreshOnce(refreshToken) {
|
|
103
78
|
const config = getConfig();
|
|
104
79
|
const fetchFn = getFetch();
|
|
105
|
-
if (!refreshToken) {
|
|
106
|
-
return "rejected";
|
|
107
|
-
}
|
|
108
80
|
const timeoutMs = config.requestTimeout ?? 3e4;
|
|
109
81
|
const controller = new AbortController();
|
|
110
82
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -119,41 +91,94 @@ async function refreshAccessToken() {
|
|
|
119
91
|
});
|
|
120
92
|
if (response.ok) {
|
|
121
93
|
let apiResponse;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
} catch {
|
|
127
|
-
return "unavailable";
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
try {
|
|
131
|
-
apiResponse = await response.json();
|
|
132
|
-
} catch {
|
|
133
|
-
return "unavailable";
|
|
134
|
-
}
|
|
94
|
+
try {
|
|
95
|
+
apiResponse = await response.json();
|
|
96
|
+
} catch {
|
|
97
|
+
return { outcome: "unavailable" };
|
|
135
98
|
}
|
|
136
99
|
const data = apiResponse?.data;
|
|
137
100
|
const tokens = data && typeof data === "object" && "data" in data ? data.data : data;
|
|
138
|
-
if (tokens?.accessToken) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
101
|
+
if (typeof tokens?.accessToken === "string" && tokens.accessToken) {
|
|
102
|
+
return {
|
|
103
|
+
outcome: "refreshed",
|
|
104
|
+
accessToken: tokens.accessToken,
|
|
105
|
+
refreshToken: typeof tokens.refreshToken === "string" && tokens.refreshToken ? tokens.refreshToken : refreshToken
|
|
106
|
+
};
|
|
143
107
|
}
|
|
144
|
-
return "unavailable";
|
|
108
|
+
return { outcome: "unavailable" };
|
|
145
109
|
}
|
|
146
|
-
if (response.status >= 500) {
|
|
147
|
-
return "unavailable";
|
|
110
|
+
if (response.status >= 500 || response.status === 429 || response.status === 408) {
|
|
111
|
+
return { outcome: "unavailable" };
|
|
148
112
|
}
|
|
149
|
-
return "rejected";
|
|
113
|
+
return { outcome: "rejected" };
|
|
150
114
|
} catch (error) {
|
|
151
115
|
config.onAuthError?.(error instanceof Error ? error : new Error("Token refresh failed"));
|
|
152
|
-
return "unavailable";
|
|
116
|
+
return { outcome: "unavailable" };
|
|
153
117
|
} finally {
|
|
154
118
|
clearTimeout(timeoutId);
|
|
155
119
|
}
|
|
156
120
|
}
|
|
121
|
+
function withRefreshLock(fn) {
|
|
122
|
+
const locks = typeof navigator !== "undefined" ? navigator.locks : void 0;
|
|
123
|
+
if (!locks) return fn();
|
|
124
|
+
const storageKey = getConfig().storageKey ?? "classic_auth";
|
|
125
|
+
return locks.request(`${storageKey}:refresh`, fn);
|
|
126
|
+
}
|
|
127
|
+
function refreshSession(options = {}) {
|
|
128
|
+
if (options.onlyIfExpired) {
|
|
129
|
+
const accessToken = getAccessToken();
|
|
130
|
+
if (accessToken && !isTokenExpired(accessToken)) return Promise.resolve("fresh");
|
|
131
|
+
}
|
|
132
|
+
if (!refreshInflight) {
|
|
133
|
+
refreshInflight = runRefresh(options).finally(() => {
|
|
134
|
+
refreshInflight = null;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return refreshInflight;
|
|
138
|
+
}
|
|
139
|
+
async function runRefresh(options) {
|
|
140
|
+
const presented = getRefreshToken();
|
|
141
|
+
if (!presented) {
|
|
142
|
+
await expireSession();
|
|
143
|
+
return "rejected";
|
|
144
|
+
}
|
|
145
|
+
return withRefreshLock(async () => {
|
|
146
|
+
const current = getRefreshToken();
|
|
147
|
+
if (current !== presented) {
|
|
148
|
+
if (!current) {
|
|
149
|
+
await expireSession();
|
|
150
|
+
return "rejected";
|
|
151
|
+
}
|
|
152
|
+
await syncSvelteStore((authStore) => authStore.rehydrate());
|
|
153
|
+
return "refreshed";
|
|
154
|
+
}
|
|
155
|
+
if (options.onlyIfExpired) {
|
|
156
|
+
const accessToken = getAccessToken();
|
|
157
|
+
if (accessToken && !isTokenExpired(accessToken)) return "fresh";
|
|
158
|
+
}
|
|
159
|
+
const delays = getConfig().refreshRetryDelays ?? DEFAULT_REFRESH_RETRY_DELAYS;
|
|
160
|
+
let attempt = await refreshOnce(current);
|
|
161
|
+
for (const delay of delays) {
|
|
162
|
+
if (attempt.outcome !== "unavailable") break;
|
|
163
|
+
await sleep(delay);
|
|
164
|
+
attempt = await refreshOnce(current);
|
|
165
|
+
}
|
|
166
|
+
if (attempt.outcome === "refreshed") {
|
|
167
|
+
await writeStoredTokens(attempt.accessToken, attempt.refreshToken);
|
|
168
|
+
return "refreshed";
|
|
169
|
+
}
|
|
170
|
+
if (attempt.outcome === "rejected") {
|
|
171
|
+
const stored = getRefreshToken();
|
|
172
|
+
if (stored && stored !== current) {
|
|
173
|
+
await syncSvelteStore((authStore) => authStore.rehydrate());
|
|
174
|
+
return "refreshed";
|
|
175
|
+
}
|
|
176
|
+
await expireSession();
|
|
177
|
+
return "rejected";
|
|
178
|
+
}
|
|
179
|
+
return "unavailable";
|
|
180
|
+
});
|
|
181
|
+
}
|
|
157
182
|
function extractData(response) {
|
|
158
183
|
if (response && typeof response === "object" && "data" in response) {
|
|
159
184
|
const dataField = response.data;
|
|
@@ -211,61 +236,14 @@ async function apiRequestInternal(endpoint, options, isRetry) {
|
|
|
211
236
|
await expireSession();
|
|
212
237
|
throw new Error("Authentication failed. Please sign in again.");
|
|
213
238
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
isRefreshing = false;
|
|
221
|
-
}
|
|
222
|
-
if (refreshResult === "refreshed") {
|
|
223
|
-
return apiRequestInternal(endpoint, options, true);
|
|
224
|
-
}
|
|
225
|
-
if (refreshResult === "rejected") {
|
|
226
|
-
onTokenRefreshFailed(true);
|
|
227
|
-
await expireSession();
|
|
228
|
-
throw new Error("Authentication failed. Please sign in again.");
|
|
229
|
-
}
|
|
230
|
-
onTokenRefreshFailed(false);
|
|
231
|
-
throw new Error("Authentication service unavailable. Please try again.");
|
|
232
|
-
} else {
|
|
233
|
-
const REFRESH_TIMEOUT_MS = 3e4;
|
|
234
|
-
return new Promise((resolve, reject) => {
|
|
235
|
-
let settled = false;
|
|
236
|
-
const refreshTimeoutId = setTimeout(() => {
|
|
237
|
-
if (!settled) {
|
|
238
|
-
settled = true;
|
|
239
|
-
unsubscribe?.();
|
|
240
|
-
reject(new Error("Token refresh timed out. Please sign in again."));
|
|
241
|
-
}
|
|
242
|
-
}, REFRESH_TIMEOUT_MS);
|
|
243
|
-
let unsubscribe = null;
|
|
244
|
-
try {
|
|
245
|
-
unsubscribe = subscribeTokenRefresh((token, terminal) => {
|
|
246
|
-
if (!settled) {
|
|
247
|
-
settled = true;
|
|
248
|
-
clearTimeout(refreshTimeoutId);
|
|
249
|
-
if (token) {
|
|
250
|
-
apiRequestInternal(endpoint, options, true).then(resolve).catch(reject);
|
|
251
|
-
} else {
|
|
252
|
-
reject(
|
|
253
|
-
new Error(
|
|
254
|
-
terminal ? "Authentication failed. Please sign in again." : "Authentication service unavailable. Please try again."
|
|
255
|
-
)
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
} catch (subscribeError) {
|
|
261
|
-
clearTimeout(refreshTimeoutId);
|
|
262
|
-
if (!settled) {
|
|
263
|
-
settled = true;
|
|
264
|
-
reject(subscribeError);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
});
|
|
239
|
+
const outcome = await refreshSession();
|
|
240
|
+
if (outcome === "refreshed") {
|
|
241
|
+
return apiRequestInternal(endpoint, options, true);
|
|
242
|
+
}
|
|
243
|
+
if (outcome === "rejected") {
|
|
244
|
+
throw new Error("Authentication failed. Please sign in again.");
|
|
268
245
|
}
|
|
246
|
+
throw new Error("Authentication service unavailable. Please try again.");
|
|
269
247
|
}
|
|
270
248
|
let data;
|
|
271
249
|
const contentType = response.headers.get("content-type");
|
|
@@ -320,6 +298,18 @@ async function apiRequestInternal(endpoint, options, isRetry) {
|
|
|
320
298
|
throw new Error("API request failed");
|
|
321
299
|
}
|
|
322
300
|
}
|
|
301
|
+
function initCrossTabSync() {
|
|
302
|
+
if (typeof window === "undefined") return () => {
|
|
303
|
+
};
|
|
304
|
+
const config = getConfig();
|
|
305
|
+
const storageKey = config.storageKey ?? "classic_auth";
|
|
306
|
+
function handleStorage(event) {
|
|
307
|
+
if (event.key !== storageKey) return;
|
|
308
|
+
void syncSvelteStore((authStore) => authStore.rehydrate());
|
|
309
|
+
}
|
|
310
|
+
window.addEventListener("storage", handleStorage);
|
|
311
|
+
return () => window.removeEventListener("storage", handleStorage);
|
|
312
|
+
}
|
|
323
313
|
var api = {
|
|
324
314
|
get: (endpoint, authenticated = false, customFetch) => apiRequest(endpoint, { method: "GET", authenticated, customFetch }),
|
|
325
315
|
post: (endpoint, body, authenticated = false, customFetch) => apiRequest(endpoint, {
|
|
@@ -830,4 +820,4 @@ var authApi = {
|
|
|
830
820
|
}
|
|
831
821
|
};
|
|
832
822
|
|
|
833
|
-
export { api, apiRequest, authApi, clearStoredAuth, extractData, getAccessToken, getRefreshToken, getSessionToken, updateStoredTokens };
|
|
823
|
+
export { api, apiRequest, authApi, clearStoredAuth, extractData, getAccessToken, getRefreshToken, getSessionToken, initCrossTabSync, refreshSession, updateStoredTokens };
|
|
@@ -173,6 +173,7 @@ var ROLE_NAMES = [
|
|
|
173
173
|
"sales_staff",
|
|
174
174
|
"stormwater_staff",
|
|
175
175
|
"warranty_staff",
|
|
176
|
+
"hotsheet_editor",
|
|
176
177
|
"employee",
|
|
177
178
|
"user",
|
|
178
179
|
"vendor",
|
|
@@ -187,7 +188,7 @@ var ROLE_HIERARCHY = {
|
|
|
187
188
|
customer: 1,
|
|
188
189
|
subcontractor: 1,
|
|
189
190
|
// Staff tier (2): the read-only `employee` floor, the field-app clones of
|
|
190
|
-
// `agent`,
|
|
191
|
+
// `agent`, every `<department>_staff` docs role, and `hotsheet_editor`.
|
|
191
192
|
employee: 2,
|
|
192
193
|
agent: 2,
|
|
193
194
|
builder: 2,
|
|
@@ -207,6 +208,7 @@ var ROLE_HIERARCHY = {
|
|
|
207
208
|
sales_staff: 2,
|
|
208
209
|
stormwater_staff: 2,
|
|
209
210
|
warranty_staff: 2,
|
|
211
|
+
hotsheet_editor: 2,
|
|
210
212
|
manager: 3,
|
|
211
213
|
admin: 4
|
|
212
214
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { authService } from './chunk-
|
|
2
|
-
import { authStore, currentUser, isAuthenticated, authActions } from './chunk-
|
|
3
|
-
import { isInitialized, initAuth, getUserRoles } from './chunk-
|
|
1
|
+
import { authService } from './chunk-2IEYKV42.js';
|
|
2
|
+
import { authStore, currentUser, isAuthenticated, authActions } from './chunk-XWJ54R6J.js';
|
|
3
|
+
import { isInitialized, initAuth, getUserRoles } from './chunk-PYCXNOMA.js';
|
|
4
4
|
|
|
5
5
|
// src/svelte/guards/auth-guard.ts
|
|
6
6
|
function checkAuth(options = {}) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { authApi } from './chunk-
|
|
2
|
-
import { isInitialized, getConfig, hasRole, hasAnyRole, hasAllRoles, decodeJWT, getStorage, getDefaultStorage } from './chunk-
|
|
1
|
+
import { authApi } from './chunk-4SLNFY2N.js';
|
|
2
|
+
import { isInitialized, getConfig, hasRole, hasAnyRole, hasAllRoles, decodeJWT, getStorage, getDefaultStorage } from './chunk-PYCXNOMA.js';
|
|
3
3
|
|
|
4
4
|
// src/svelte/stores/auth.svelte.ts
|
|
5
5
|
var STORAGE_VERSION = 2;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { e as LoginCredentials, f as LoginResponse, g as LogoutResponse, R as RegisterData, k as RegisterResponse, p as User, j as ProfileUpdateData, C as ChangePasswordData, n as Session, A as ApiKey, c as CreateApiKeyRequest, d as CreateApiKeyResponse, U as UpdateApiKeyRequest, i as MFAStatus, h as MFASetupResponse, M as MFAChallengeData, D as Device, q as UserPreferences, L as LinkedAccount, m as SecurityEvent, P as Pagination, r as UserRolesResponse } from '../types-
|
|
2
|
-
export { a as AuthConfig, b as AuthState, l as ResetPasswordData, S as SSOConfig, o as StorageAdapter, s as createMemoryStorage, t as createSessionStorage, u as getConfig, v as getDefaultStorage, w as getFetch, x as getStorage, y as initAuth, z as isInitialized, B as resetConfig } from '../types-
|
|
3
|
-
export { A as AuthService, L as LoginOptions, M as MFAVerifyOptions, R as RoleDeniedError, a as authService, f as formatUserRoles, g as getAvatarFallback, b as getDisplayName, c as getGreeting, d as getUserEmail, e as getUserInitials, i as isRoleDeniedError } from '../user-utils-
|
|
1
|
+
import { e as LoginCredentials, f as LoginResponse, g as LogoutResponse, R as RegisterData, k as RegisterResponse, p as User, j as ProfileUpdateData, C as ChangePasswordData, n as Session, A as ApiKey, c as CreateApiKeyRequest, d as CreateApiKeyResponse, U as UpdateApiKeyRequest, i as MFAStatus, h as MFASetupResponse, M as MFAChallengeData, D as Device, q as UserPreferences, L as LinkedAccount, m as SecurityEvent, P as Pagination, r as UserRolesResponse } from '../types-Bqh2gkvu.js';
|
|
2
|
+
export { a as AuthConfig, b as AuthState, l as ResetPasswordData, S as SSOConfig, o as StorageAdapter, s as createMemoryStorage, t as createSessionStorage, u as getConfig, v as getDefaultStorage, w as getFetch, x as getStorage, y as initAuth, z as isInitialized, B as resetConfig } from '../types-Bqh2gkvu.js';
|
|
3
|
+
export { A as AuthService, L as LoginOptions, M as MFAVerifyOptions, R as RoleDeniedError, a as authService, f as formatUserRoles, g as getAvatarFallback, b as getDisplayName, c as getGreeting, d as getUserEmail, e as getUserInitials, i as isRoleDeniedError } from '../user-utils-92PeSjcw.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* HTTP Client
|
|
@@ -39,6 +39,26 @@ interface ApiResponse<T = unknown> {
|
|
|
39
39
|
code?: string;
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Outcome of {@link refreshSession}:
|
|
44
|
+
* - `refreshed`: the stored tokens are new — either this call refreshed them
|
|
45
|
+
* or another tab/caller did while this call waited its turn.
|
|
46
|
+
* - `fresh`: nothing to do — `onlyIfExpired` was set and the stored access
|
|
47
|
+
* token is still valid.
|
|
48
|
+
* - `rejected`: the server definitively rejected the refresh token (4xx) —
|
|
49
|
+
* the session is unrecoverable and has been cleared.
|
|
50
|
+
* - `unavailable`: the server could not be reached or errored (network
|
|
51
|
+
* failure, timeout, 5xx, 429) even after retries — the refresh token may
|
|
52
|
+
* still be perfectly good, so the session is kept and the caller can retry.
|
|
53
|
+
*/
|
|
54
|
+
type RefreshOutcome = 'refreshed' | 'fresh' | 'rejected' | 'unavailable';
|
|
55
|
+
interface RefreshSessionOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Skip the network call (→ `fresh`) when the stored access token has not
|
|
58
|
+
* expired yet. Default `false`: refresh unconditionally.
|
|
59
|
+
*/
|
|
60
|
+
onlyIfExpired?: boolean;
|
|
61
|
+
}
|
|
42
62
|
/**
|
|
43
63
|
* Get the current access token from storage.
|
|
44
64
|
*/
|
|
@@ -53,18 +73,39 @@ declare function getRefreshToken(): string | null;
|
|
|
53
73
|
declare function getSessionToken(): string | null;
|
|
54
74
|
/**
|
|
55
75
|
* Update stored tokens.
|
|
56
|
-
* Also updates the Svelte auth store if available.
|
|
76
|
+
* Also updates the Svelte auth store if available (asynchronously).
|
|
57
77
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
78
|
+
* Prefer {@link refreshSession} over calling this with tokens obtained from a
|
|
79
|
+
* hand-rolled `/auth/refresh` call: that path bypasses the single-flight and
|
|
80
|
+
* cross-tab serialization, so it can race the client's own refresh and
|
|
81
|
+
* orphan a rotated token.
|
|
62
82
|
*/
|
|
63
83
|
declare function updateStoredTokens(accessToken: string, refreshToken: string): void;
|
|
64
84
|
/**
|
|
65
85
|
* Clear stored auth data.
|
|
66
86
|
*/
|
|
67
87
|
declare function clearStoredAuth(): void;
|
|
88
|
+
/**
|
|
89
|
+
* Refresh the session's tokens. The single refresh path for the whole client:
|
|
90
|
+
*
|
|
91
|
+
* - **Single-flight per tab.** Concurrent callers (several 401s, a proactive
|
|
92
|
+
* refresh before navigation, an upload client) share one in-flight call.
|
|
93
|
+
* - **Serialized across tabs** via a Web Lock, and reconciled: if another tab
|
|
94
|
+
* rotated the token while this call waited, the stored tokens are adopted
|
|
95
|
+
* (`refreshed`) instead of re-presenting a token the server has retired.
|
|
96
|
+
* - **Transient failures retried** with `AuthConfig.refreshRetryDelays`
|
|
97
|
+
* backoff, re-presenting the same token (a failed attempt never reached the
|
|
98
|
+
* rotation write).
|
|
99
|
+
* - **Consequences applied here.** `refreshed` → tokens stored and the Svelte
|
|
100
|
+
* store updated before this resolves; `rejected` → the session is cleared
|
|
101
|
+
* (`handleSessionExpired`, `onSessionExpired`, `onLogout`); `unavailable` →
|
|
102
|
+
* the session is left intact for a later retry.
|
|
103
|
+
*
|
|
104
|
+
* Apps that refresh proactively (e.g. before a route guard reads claims)
|
|
105
|
+
* should call this rather than `authApi.refreshToken`, which bypasses all of
|
|
106
|
+
* the above.
|
|
107
|
+
*/
|
|
108
|
+
declare function refreshSession(options?: RefreshSessionOptions): Promise<RefreshOutcome>;
|
|
68
109
|
/**
|
|
69
110
|
* Helper to extract data from CHAPI response wrapper.
|
|
70
111
|
*
|
|
@@ -81,6 +122,17 @@ declare function extractData<T>(response: {
|
|
|
81
122
|
* Make an API request.
|
|
82
123
|
*/
|
|
83
124
|
declare function apiRequest<T = unknown>(endpoint: string, options?: ApiRequestOptions): Promise<T>;
|
|
125
|
+
/**
|
|
126
|
+
* Set up cross-tab session synchronization via the `storage` event.
|
|
127
|
+
* When another tab refreshes tokens or signs out, this tab's Svelte store
|
|
128
|
+
* (when present) is rehydrated from storage so its claims and
|
|
129
|
+
* `isAuthenticated` follow. Requests already read tokens from storage on
|
|
130
|
+
* every call, so they pick up the change without this; the store is what
|
|
131
|
+
* would otherwise go stale.
|
|
132
|
+
*
|
|
133
|
+
* Call once during app initialization.
|
|
134
|
+
*/
|
|
135
|
+
declare function initCrossTabSync(): () => void;
|
|
84
136
|
/**
|
|
85
137
|
* Convenience methods for common HTTP methods.
|
|
86
138
|
*/
|
|
@@ -475,10 +527,12 @@ declare function extractClaims<T extends string>(token: string, claims: T[]): Pi
|
|
|
475
527
|
* the first match, which is what makes the result deterministic when several
|
|
476
528
|
* roles share a tier (e.g. `agent` + `builder`).
|
|
477
529
|
*
|
|
478
|
-
* Mirrors `ROLE_NAMES` in the API. `builder`/`customer_service`/`
|
|
479
|
-
*
|
|
480
|
-
* are grant-on-top docs roles held alongside another
|
|
481
|
-
* the API lists in `DEPARTMENT_SCOPES`;
|
|
530
|
+
* Mirrors `ROLE_NAMES` in the API. `builder`/`customer_service`/`stormwater`
|
|
531
|
+
* are staff-tier clones of `agent` and `demo` a read-only one; the
|
|
532
|
+
* `<department>_staff` roles are grant-on-top docs roles held alongside another
|
|
533
|
+
* role, one per department the API lists in `DEPARTMENT_SCOPES`;
|
|
534
|
+
* `hotsheet_editor` is a grant-on-top role for the Hotsheet hub's write
|
|
535
|
+
* surface; `employee` is the read-only base staff
|
|
482
536
|
* floor (default for Authentik SSO); `vendor`/`customer`/`subcontractor` are
|
|
483
537
|
* clones of `user`, row-scoped to their own homes.
|
|
484
538
|
*
|
|
@@ -486,7 +540,7 @@ declare function extractClaims<T extends string>(token: string, claims: T[]): Pi
|
|
|
486
540
|
* field app's clone of `agent`, the second is that department's docs role.
|
|
487
541
|
* Someone on the stormwater team who also reads the docs holds both.
|
|
488
542
|
*/
|
|
489
|
-
declare const ROLE_NAMES: readonly ["admin", "manager", "agent", "builder", "customer_service", "demo", "stormwater", "accounting_staff", "architecture_staff", "construction_staff", "crl_staff", "design_staff", "hr_staff", "it_staff", "landdev_staff", "marketing_staff", "purchasing_staff", "sales_staff", "stormwater_staff", "warranty_staff", "employee", "user", "vendor", "customer", "subcontractor", "guest"];
|
|
543
|
+
declare const ROLE_NAMES: readonly ["admin", "manager", "agent", "builder", "customer_service", "demo", "stormwater", "accounting_staff", "architecture_staff", "construction_staff", "crl_staff", "design_staff", "hr_staff", "it_staff", "landdev_staff", "marketing_staff", "purchasing_staff", "sales_staff", "stormwater_staff", "warranty_staff", "hotsheet_editor", "employee", "user", "vendor", "customer", "subcontractor", "guest"];
|
|
490
544
|
/**
|
|
491
545
|
* A known role name.
|
|
492
546
|
*
|
|
@@ -565,4 +619,4 @@ declare function hasAnyRole(user: Pick<User, 'roles'> | null | undefined, roles:
|
|
|
565
619
|
*/
|
|
566
620
|
declare function hasAllRoles(user: Pick<User, 'roles'> | null | undefined, roles: readonly string[]): boolean;
|
|
567
621
|
|
|
568
|
-
export { ApiKey, type ApiRequestOptions, type ApiResponse, ChangePasswordData, CreateApiKeyRequest, CreateApiKeyResponse, Device, type JWTPayload, LinkedAccount, LoginCredentials, LoginResponse, LogoutResponse, MFAChallengeData, MFASetupResponse, MFAStatus, Pagination, ProfileUpdateData, ROLE_HIERARCHY, ROLE_NAMES, RegisterData, RegisterResponse, type RoleName, SecurityEvent, Session, UpdateApiKeyRequest, User, UserPreferences, UserRolesResponse, api, apiRequest, authApi, clearStoredAuth, computePrimaryRole, decodeJWT, extractClaims, extractData, getAccessToken, getAvailableMethods, getEffectiveLevel, getMfaToken, getRefreshToken, getSessionToken, getTokenExpiration, getTokenRemainingTime, getUserRoles, hasAllRoles, hasAnyRole, hasRole, isLoginSuccessResponse, isMfaChallengeResponse, isTokenExpired, updateStoredTokens };
|
|
622
|
+
export { ApiKey, type ApiRequestOptions, type ApiResponse, ChangePasswordData, CreateApiKeyRequest, CreateApiKeyResponse, Device, type JWTPayload, LinkedAccount, LoginCredentials, LoginResponse, LogoutResponse, MFAChallengeData, MFASetupResponse, MFAStatus, Pagination, ProfileUpdateData, ROLE_HIERARCHY, ROLE_NAMES, type RefreshOutcome, type RefreshSessionOptions, RegisterData, RegisterResponse, type RoleName, SecurityEvent, Session, UpdateApiKeyRequest, User, UserPreferences, UserRolesResponse, api, apiRequest, authApi, clearStoredAuth, computePrimaryRole, decodeJWT, extractClaims, extractData, getAccessToken, getAvailableMethods, getEffectiveLevel, getMfaToken, getRefreshToken, getSessionToken, getTokenExpiration, getTokenRemainingTime, getUserRoles, hasAllRoles, hasAnyRole, hasRole, initCrossTabSync, isLoginSuccessResponse, isMfaChallengeResponse, isTokenExpired, refreshSession, updateStoredTokens };
|
package/dist/core/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { AuthService, RoleDeniedError, authService, formatUserRoles, getAvailableMethods, getAvatarFallback, getDisplayName, getGreeting, getMfaToken, getUserEmail, getUserInitials, isLoginSuccessResponse, isMfaChallengeResponse, isRoleDeniedError } from '../chunk-
|
|
2
|
-
export { api, apiRequest, authApi, clearStoredAuth, extractData, getAccessToken, getRefreshToken, getSessionToken, updateStoredTokens } from '../chunk-
|
|
3
|
-
export { ROLE_HIERARCHY, ROLE_NAMES, computePrimaryRole, createMemoryStorage, createSessionStorage, decodeJWT, extractClaims, getConfig, getDefaultStorage, getEffectiveLevel, getFetch, getStorage, getTokenExpiration, getTokenRemainingTime, getUserRoles, hasAllRoles, hasAnyRole, hasRole, initAuth, isInitialized, isTokenExpired, resetConfig } from '../chunk-
|
|
1
|
+
export { AuthService, RoleDeniedError, authService, formatUserRoles, getAvailableMethods, getAvatarFallback, getDisplayName, getGreeting, getMfaToken, getUserEmail, getUserInitials, isLoginSuccessResponse, isMfaChallengeResponse, isRoleDeniedError } from '../chunk-2IEYKV42.js';
|
|
2
|
+
export { api, apiRequest, authApi, clearStoredAuth, extractData, getAccessToken, getRefreshToken, getSessionToken, initCrossTabSync, refreshSession, updateStoredTokens } from '../chunk-4SLNFY2N.js';
|
|
3
|
+
export { ROLE_HIERARCHY, ROLE_NAMES, computePrimaryRole, createMemoryStorage, createSessionStorage, decodeJWT, extractClaims, getConfig, getDefaultStorage, getEffectiveLevel, getFetch, getStorage, getTokenExpiration, getTokenRemainingTime, getUserRoles, hasAllRoles, hasAnyRole, hasRole, initAuth, isInitialized, isTokenExpired, resetConfig } from '../chunk-PYCXNOMA.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApiKey, a as AuthConfig, b as AuthState, C as ChangePasswordData, c as CreateApiKeyRequest, d as CreateApiKeyResponse, D as Device, L as LinkedAccount, e as LoginCredentials, f as LoginResponse, g as LogoutResponse, M as MFAChallengeData, h as MFASetupResponse, i as MFAStatus, P as Pagination, j as ProfileUpdateData, R as RegisterData, k as RegisterResponse, l as ResetPasswordData, S as SSOConfig, m as SecurityEvent, n as Session, o as StorageAdapter, U as UpdateApiKeyRequest, p as User, q as UserPreferences, r as UserRolesResponse, s as createMemoryStorage, t as createSessionStorage, u as getConfig, v as getDefaultStorage, w as getFetch, x as getStorage, y as initAuth, z as isInitialized, B as resetConfig } from './types-
|
|
2
|
-
export { ApiRequestOptions, ApiResponse, JWTPayload, ROLE_HIERARCHY, ROLE_NAMES, RoleName, api, apiRequest, authApi, clearStoredAuth, computePrimaryRole, decodeJWT, extractClaims, extractData, getAccessToken, getAvailableMethods, getEffectiveLevel, getMfaToken, getRefreshToken, getSessionToken, getTokenExpiration, getTokenRemainingTime, getUserRoles, hasAllRoles, hasAnyRole, hasRole, isLoginSuccessResponse, isMfaChallengeResponse, isTokenExpired, updateStoredTokens } from './core/index.js';
|
|
3
|
-
export { A as AuthService, L as LoginOptions, M as MFAVerifyOptions, R as RoleDeniedError, a as authService, f as formatUserRoles, g as getAvatarFallback, b as getDisplayName, c as getGreeting, d as getUserEmail, e as getUserInitials, i as isRoleDeniedError } from './user-utils-
|
|
1
|
+
export { A as ApiKey, a as AuthConfig, b as AuthState, C as ChangePasswordData, c as CreateApiKeyRequest, d as CreateApiKeyResponse, D as Device, L as LinkedAccount, e as LoginCredentials, f as LoginResponse, g as LogoutResponse, M as MFAChallengeData, h as MFASetupResponse, i as MFAStatus, P as Pagination, j as ProfileUpdateData, R as RegisterData, k as RegisterResponse, l as ResetPasswordData, S as SSOConfig, m as SecurityEvent, n as Session, o as StorageAdapter, U as UpdateApiKeyRequest, p as User, q as UserPreferences, r as UserRolesResponse, s as createMemoryStorage, t as createSessionStorage, u as getConfig, v as getDefaultStorage, w as getFetch, x as getStorage, y as initAuth, z as isInitialized, B as resetConfig } from './types-Bqh2gkvu.js';
|
|
2
|
+
export { ApiRequestOptions, ApiResponse, JWTPayload, ROLE_HIERARCHY, ROLE_NAMES, RefreshOutcome, RefreshSessionOptions, RoleName, api, apiRequest, authApi, clearStoredAuth, computePrimaryRole, decodeJWT, extractClaims, extractData, getAccessToken, getAvailableMethods, getEffectiveLevel, getMfaToken, getRefreshToken, getSessionToken, getTokenExpiration, getTokenRemainingTime, getUserRoles, hasAllRoles, hasAnyRole, hasRole, initCrossTabSync, isLoginSuccessResponse, isMfaChallengeResponse, isTokenExpired, refreshSession, updateStoredTokens } from './core/index.js';
|
|
3
|
+
export { A as AuthService, L as LoginOptions, M as MFAVerifyOptions, R as RoleDeniedError, a as authService, f as formatUserRoles, g as getAvatarFallback, b as getDisplayName, c as getGreeting, d as getUserEmail, e as getUserInitials, i as isRoleDeniedError } from './user-utils-92PeSjcw.js';
|
|
4
4
|
export { AuthClient, AuthGuardOptions, AuthGuardResult, AuthHookOptions, CreateAuthClientOptions, NavFilterOptions, RoleRestrictedItem, authActions, authStore, canAccess, checkAuth, createAuthClient, createAuthGuard, createAuthHook, createNavFilter, currentUser, filterByAccess, filterNavSections, isAuthenticated, matchesRoute, protectedLoad, requireAuth, requirePermission, requireRole, routePatterns } from './svelte/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { canAccess, checkAuth, createAuthClient, createAuthGuard, createAuthHook, createNavFilter, filterByAccess, filterNavSections, matchesRoute, protectedLoad, requireAuth, requirePermission, requireRole, routePatterns } from './chunk-
|
|
2
|
-
export { AuthService, RoleDeniedError, authService, formatUserRoles, getAvailableMethods, getAvatarFallback, getDisplayName, getGreeting, getMfaToken, getUserEmail, getUserInitials, isLoginSuccessResponse, isMfaChallengeResponse, isRoleDeniedError } from './chunk-
|
|
3
|
-
export { authActions, authStore, currentUser, isAuthenticated } from './chunk-
|
|
4
|
-
export { api, apiRequest, authApi, clearStoredAuth, extractData, getAccessToken, getRefreshToken, getSessionToken, updateStoredTokens } from './chunk-
|
|
5
|
-
export { ROLE_HIERARCHY, ROLE_NAMES, computePrimaryRole, createMemoryStorage, createSessionStorage, decodeJWT, extractClaims, getConfig, getDefaultStorage, getEffectiveLevel, getFetch, getStorage, getTokenExpiration, getTokenRemainingTime, getUserRoles, hasAllRoles, hasAnyRole, hasRole, initAuth, isInitialized, isTokenExpired, resetConfig } from './chunk-
|
|
1
|
+
export { canAccess, checkAuth, createAuthClient, createAuthGuard, createAuthHook, createNavFilter, filterByAccess, filterNavSections, matchesRoute, protectedLoad, requireAuth, requirePermission, requireRole, routePatterns } from './chunk-VLDCDFEN.js';
|
|
2
|
+
export { AuthService, RoleDeniedError, authService, formatUserRoles, getAvailableMethods, getAvatarFallback, getDisplayName, getGreeting, getMfaToken, getUserEmail, getUserInitials, isLoginSuccessResponse, isMfaChallengeResponse, isRoleDeniedError } from './chunk-2IEYKV42.js';
|
|
3
|
+
export { authActions, authStore, currentUser, isAuthenticated } from './chunk-XWJ54R6J.js';
|
|
4
|
+
export { api, apiRequest, authApi, clearStoredAuth, extractData, getAccessToken, getRefreshToken, getSessionToken, initCrossTabSync, refreshSession, updateStoredTokens } from './chunk-4SLNFY2N.js';
|
|
5
|
+
export { ROLE_HIERARCHY, ROLE_NAMES, computePrimaryRole, createMemoryStorage, createSessionStorage, decodeJWT, extractClaims, getConfig, getDefaultStorage, getEffectiveLevel, getFetch, getStorage, getTokenExpiration, getTokenRemainingTime, getUserRoles, hasAllRoles, hasAnyRole, hasRole, initAuth, isInitialized, isTokenExpired, resetConfig } from './chunk-PYCXNOMA.js';
|
package/dist/svelte/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { b as AuthState, p as User, a as AuthConfig } from '../types-
|
|
2
|
-
export { y as initAuth, z as isInitialized } from '../types-
|
|
3
|
-
import { a as authService } from '../user-utils-
|
|
4
|
-
export { R as RoleDeniedError, f as formatUserRoles, g as getAvatarFallback, b as getDisplayName, c as getGreeting, d as getUserEmail, e as getUserInitials, i as isRoleDeniedError } from '../user-utils-
|
|
1
|
+
import { b as AuthState, p as User, a as AuthConfig } from '../types-Bqh2gkvu.js';
|
|
2
|
+
export { y as initAuth, z as isInitialized } from '../types-Bqh2gkvu.js';
|
|
3
|
+
import { a as authService } from '../user-utils-92PeSjcw.js';
|
|
4
|
+
export { R as RoleDeniedError, f as formatUserRoles, g as getAvatarFallback, b as getDisplayName, c as getGreeting, d as getUserEmail, e as getUserInitials, i as isRoleDeniedError } from '../user-utils-92PeSjcw.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Auth Store
|
package/dist/svelte/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { canAccess, checkAuth, createAuthClient, createAuthGuard, createAuthHook, createNavFilter, filterByAccess, filterNavSections, matchesRoute, protectedLoad, requireAuth, requirePermission, requireRole, routePatterns } from '../chunk-
|
|
2
|
-
export { RoleDeniedError, formatUserRoles, getAvatarFallback, getDisplayName, getGreeting, getUserEmail, getUserInitials, isRoleDeniedError } from '../chunk-
|
|
3
|
-
export { authActions, authStore, currentUser, isAuthenticated } from '../chunk-
|
|
4
|
-
import '../chunk-
|
|
5
|
-
export { initAuth, isInitialized } from '../chunk-
|
|
1
|
+
export { canAccess, checkAuth, createAuthClient, createAuthGuard, createAuthHook, createNavFilter, filterByAccess, filterNavSections, matchesRoute, protectedLoad, requireAuth, requirePermission, requireRole, routePatterns } from '../chunk-VLDCDFEN.js';
|
|
2
|
+
export { RoleDeniedError, formatUserRoles, getAvatarFallback, getDisplayName, getGreeting, getUserEmail, getUserInitials, isRoleDeniedError } from '../chunk-2IEYKV42.js';
|
|
3
|
+
export { authActions, authStore, currentUser, isAuthenticated } from '../chunk-XWJ54R6J.js';
|
|
4
|
+
import '../chunk-4SLNFY2N.js';
|
|
5
|
+
export { initAuth, isInitialized } from '../chunk-PYCXNOMA.js';
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { p as User, D as Device, f as LoginResponse, m as SecurityEvent, n as Session, A as ApiKey, L as LinkedAccount, g as LogoutResponse, h as MFASetupResponse, i as MFAStatus, k as RegisterResponse, q as UserPreferences, o as StorageAdapter, b as AuthState, a as AuthConfig } from '../types-
|
|
1
|
+
import { p as User, D as Device, f as LoginResponse, m as SecurityEvent, n as Session, A as ApiKey, L as LinkedAccount, g as LogoutResponse, h as MFASetupResponse, i as MFAStatus, k as RegisterResponse, q as UserPreferences, o as StorageAdapter, b as AuthState, a as AuthConfig } from '../types-Bqh2gkvu.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* User Fixtures
|
package/dist/testing/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { hasRole, hasAnyRole, hasAllRoles, initAuth, resetConfig, getUserRoles, isTokenExpired, decodeJWT } from '../chunk-
|
|
1
|
+
import { hasRole, hasAnyRole, hasAllRoles, initAuth, resetConfig, getUserRoles, isTokenExpired, decodeJWT } from '../chunk-PYCXNOMA.js';
|
|
2
2
|
|
|
3
3
|
// src/testing/fixtures/users.ts
|
|
4
4
|
var mockUser = {
|
|
@@ -52,6 +52,12 @@ interface AuthConfig {
|
|
|
52
52
|
onSessionExpired?: (currentPath: string) => void;
|
|
53
53
|
/** Request timeout in milliseconds (default: 30000) */
|
|
54
54
|
requestTimeout?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Backoff (ms) between retries of a token refresh that failed transiently
|
|
57
|
+
* (network error, timeout, 5xx, 429). One retry per entry; `[]` disables
|
|
58
|
+
* retries. Default: `[1000, 3000]` — three attempts in all.
|
|
59
|
+
*/
|
|
60
|
+
refreshRetryDelays?: number[];
|
|
55
61
|
/** SSO configuration */
|
|
56
62
|
sso?: SSOConfig;
|
|
57
63
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { e as LoginCredentials, f as LoginResponse, g as LogoutResponse, R as RegisterData, k as RegisterResponse, p as User, j as ProfileUpdateData, n as Session, A as ApiKey, c as CreateApiKeyRequest, d as CreateApiKeyResponse, U as UpdateApiKeyRequest, i as MFAStatus, h as MFASetupResponse, M as MFAChallengeData, D as Device, q as UserPreferences, L as LinkedAccount, m as SecurityEvent, P as Pagination } from './types-
|
|
1
|
+
import { e as LoginCredentials, f as LoginResponse, g as LogoutResponse, R as RegisterData, k as RegisterResponse, p as User, j as ProfileUpdateData, n as Session, A as ApiKey, c as CreateApiKeyRequest, d as CreateApiKeyResponse, U as UpdateApiKeyRequest, i as MFAStatus, h as MFASetupResponse, M as MFAChallengeData, D as Device, q as UserPreferences, L as LinkedAccount, m as SecurityEvent, P as Pagination } from './types-Bqh2gkvu.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Auth Service
|
package/package.json
CHANGED