@indusaction/cms-auth 0.1.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 ADDED
@@ -0,0 +1,82 @@
1
+ # @indusaction/cms-auth
2
+
3
+ Shared OTP + cookie JWT authentication for IndusAction CMS **web** (`campaign-fe`) and **mobile** (`case-fe`).
4
+
5
+ Works with **campaign-be**: HttpOnly `{appSource}_cms_token` cookies, `withCredentials`, 401 → refresh.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @indusaction/cms-auth axios js-cookie antd react react-dom react-router-dom
11
+
12
+ # Optional — wrap the app with ThemeProvider from the UI package for brand colors
13
+ npm install @indusaction/cms-design-system
14
+ ```
15
+
16
+ ## Quick start
17
+
18
+ ```tsx
19
+ import {
20
+ createAuthClient,
21
+ AuthProvider,
22
+ IdentifierForm,
23
+ OtpForm,
24
+ ProtectedRoute,
25
+ GuestRoute,
26
+ MOBILE_SEND_OTP_PATH,
27
+ } from "@indusaction/cms-auth";
28
+ import { ThemeProvider } from "@indusaction/cms-design-system";
29
+ ```
30
+
31
+ ```tsx
32
+ // campaign-fe (web)
33
+ const authClient = createAuthClient({
34
+ baseURL: import.meta.env.VITE_IA_CMS_BASEURL,
35
+ appSource: import.meta.env.VITE_APP_SOURCE, // e.g. campaign-local
36
+ profilePrefix: "campaign",
37
+ });
38
+
39
+ // case-fe (mobile) — only send-otp path differs
40
+ const caseAuthClient = createAuthClient({
41
+ baseURL: import.meta.env.VITE_API_BASE_URL,
42
+ appSource: import.meta.env.VITE_APP_SOURCE, // e.g. case-local
43
+ profilePrefix: "case",
44
+ paths: {
45
+ sendOtp: MOBILE_SEND_OTP_PATH,
46
+ login: "auth/login/",
47
+ refresh: "auth/token/refresh/",
48
+ logout: "auth/logout/",
49
+ },
50
+ loginPath: "/auth/login",
51
+ });
52
+
53
+ function App() {
54
+ return (
55
+ <ThemeProvider>
56
+ <AuthProvider
57
+ client={authClient}
58
+ onLoginSuccess={() => {
59
+ window.location.assign("/");
60
+ }}
61
+ >
62
+ {/* routes */}
63
+ </AuthProvider>
64
+ </ThemeProvider>
65
+ );
66
+ }
67
+ ```
68
+
69
+ Use `authClient.api` for authenticated API calls (same Axios instance with refresh interceptor).
70
+
71
+ ## Package surface
72
+
73
+ | Export | Role |
74
+ |--------|------|
75
+ | `createAuthClient` | Axios + OTP/login/logout/refresh + cookie helpers |
76
+ | `AuthProvider` / `useAuth` | `signIn`, `verifyOtp`, `logout` |
77
+ | `ProtectedRoute` / `GuestRoute` | Cookie-based route guards |
78
+ | `IdentifierForm` / `OtpForm` | Shared login UI (Ant Design; themed via app `ThemeProvider`) |
79
+ | `useAutoLogout` | Optional expiry-cookie logout (case-fe) |
80
+ | `buildCookieKeys` / storage helpers | Low-level cookie/localStorage |
81
+
82
+ App-specific flows (permissions routes, Glific, public Bearer session, offline sync) stay in each app.
package/dist/index.cjs ADDED
@@ -0,0 +1,558 @@
1
+ 'use strict';
2
+
3
+ var Cookies = require('js-cookie');
4
+ var axios = require('axios');
5
+ var react = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var reactRouterDom = require('react-router-dom');
8
+ var antd = require('antd');
9
+
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
+
12
+ var Cookies__default = /*#__PURE__*/_interopDefault(Cookies);
13
+ var axios__default = /*#__PURE__*/_interopDefault(axios);
14
+
15
+ // src/types.ts
16
+ var DEFAULT_AUTH_PATHS = {
17
+ sendOtp: "api/v1/users/send-otp/",
18
+ login: "api/v1/auth/login/",
19
+ refresh: "api/v1/auth/token/refresh/",
20
+ logout: "api/v1/auth/logout/"
21
+ };
22
+ var MOBILE_SEND_OTP_PATH = "users/send-otp-mobile/";
23
+
24
+ // src/cookies.ts
25
+ function buildCookieKeys(appSource, profilePrefix) {
26
+ return {
27
+ isLoggedIn: `${appSource}_is_logged_in`,
28
+ tokenExpiry: `${appSource}_cms_token_expiry`,
29
+ userId: `${profilePrefix}_user_id`,
30
+ userRole: `${profilePrefix}_user_role`,
31
+ userType: `${profilePrefix}_user_type`,
32
+ userFirstName: `${profilePrefix}_user_first_name`,
33
+ userLastName: `${profilePrefix}_user_last_name`,
34
+ userPermissions: `${profilePrefix}_user_permissions`,
35
+ notification: `${profilePrefix}_notification`
36
+ };
37
+ }
38
+ function authCookieKeyList(keys) {
39
+ return Object.values(keys);
40
+ }
41
+ function isLoggedIn(keys) {
42
+ return Cookies__default.default.get(keys.isLoggedIn) === "true";
43
+ }
44
+ function getTokenExpiry(keys) {
45
+ const raw = Cookies__default.default.get(keys.tokenExpiry);
46
+ if (!raw) return null;
47
+ const value = Number(raw);
48
+ return Number.isFinite(value) ? value : null;
49
+ }
50
+ function getSessionProfile(keys, permissionsStorageKey) {
51
+ const idx = Cookies__default.default.get(keys.userId);
52
+ const role = Cookies__default.default.get(keys.userRole);
53
+ const userType = Cookies__default.default.get(keys.userType);
54
+ if (!idx || !role || !userType) return null;
55
+ let permissions = [];
56
+ try {
57
+ const raw = localStorage.getItem(permissionsStorageKey);
58
+ if (raw) permissions = JSON.parse(raw);
59
+ } catch {
60
+ permissions = [];
61
+ }
62
+ return {
63
+ idx,
64
+ role,
65
+ userType,
66
+ firstName: Cookies__default.default.get(keys.userFirstName),
67
+ lastName: Cookies__default.default.get(keys.userLastName),
68
+ permissions
69
+ };
70
+ }
71
+ function persistSessionProfile(user, keys, permissionsStorageKey) {
72
+ const permissions = user.user_permissions ?? [];
73
+ localStorage.setItem(permissionsStorageKey, JSON.stringify(permissions));
74
+ Cookies__default.default.set(keys.userId, user.idx);
75
+ Cookies__default.default.set(keys.userRole, user.role);
76
+ Cookies__default.default.set(keys.userType, user.user_type);
77
+ if (user.first_name) Cookies__default.default.set(keys.userFirstName, user.first_name);
78
+ if (user.last_name) Cookies__default.default.set(keys.userLastName, user.last_name);
79
+ if (permissions.length) {
80
+ Cookies__default.default.set(keys.userPermissions, JSON.stringify(permissions));
81
+ }
82
+ }
83
+ function clearAuthStorage(keys, permissionsStorageKey, extraClearKeys = []) {
84
+ authCookieKeyList(keys).forEach((key) => Cookies__default.default.remove(key));
85
+ localStorage.removeItem(permissionsStorageKey);
86
+ extraClearKeys.forEach((key) => {
87
+ localStorage.removeItem(key);
88
+ sessionStorage.removeItem(key);
89
+ Cookies__default.default.remove(key);
90
+ });
91
+ }
92
+ function joinPath(baseURL, path) {
93
+ const base = baseURL.replace(/\/+$/, "");
94
+ const normalized = path.replace(/^\/+/, "");
95
+ return `${base}/${normalized}`;
96
+ }
97
+ function createAuthClient(options) {
98
+ const paths = {
99
+ ...DEFAULT_AUTH_PATHS,
100
+ ...options.paths
101
+ };
102
+ const cookieKeys = buildCookieKeys(options.appSource, options.profilePrefix);
103
+ const permissionsStorageKey = options.permissionsStorageKey ?? `${options.profilePrefix}_user_permissions`;
104
+ const extraClearKeys = options.extraClearKeys ?? [];
105
+ const loginPath = options.loginPath ?? "/login";
106
+ const api = axios__default.default.create({
107
+ baseURL: options.baseURL,
108
+ withCredentials: true
109
+ });
110
+ let refreshPromise = null;
111
+ const refresh = async () => {
112
+ if (!refreshPromise) {
113
+ refreshPromise = api.post(paths.refresh).then(() => void 0).finally(() => {
114
+ refreshPromise = null;
115
+ });
116
+ }
117
+ return refreshPromise;
118
+ };
119
+ const clearSession = async (clearOptions = {}) => {
120
+ const shouldRedirect = clearOptions.redirect !== false;
121
+ try {
122
+ await api.post(paths.logout);
123
+ } catch {
124
+ }
125
+ clearAuthStorage(cookieKeys, permissionsStorageKey, extraClearKeys);
126
+ options.onSessionCleared?.();
127
+ if (shouldRedirect && typeof window !== "undefined" && window.location.pathname !== loginPath) {
128
+ window.location.replace(loginPath);
129
+ }
130
+ };
131
+ api.interceptors.response.use(
132
+ (response) => response,
133
+ async (error) => {
134
+ const originalRequest = error.config;
135
+ const status = error.response?.status;
136
+ const url = originalRequest?.url ?? "";
137
+ if (status === 401 && originalRequest && !originalRequest._retry && !url.includes(paths.refresh)) {
138
+ originalRequest._retry = true;
139
+ try {
140
+ await refresh();
141
+ return api(originalRequest);
142
+ } catch {
143
+ await clearSession();
144
+ }
145
+ }
146
+ return Promise.reject(error);
147
+ }
148
+ );
149
+ const sendOtp = async (payload) => {
150
+ const { data } = await api.post(paths.sendOtp, payload);
151
+ return data;
152
+ };
153
+ const login = async (payload) => {
154
+ const { data } = await api.post(
155
+ paths.login,
156
+ payload
157
+ );
158
+ const user = data.data;
159
+ persistSessionProfile(user, cookieKeys, permissionsStorageKey);
160
+ return user;
161
+ };
162
+ const logout = async (clearOptions = {}) => {
163
+ await clearSession(clearOptions);
164
+ };
165
+ return {
166
+ api,
167
+ paths,
168
+ cookieKeys,
169
+ permissionsStorageKey,
170
+ options: {
171
+ ...options,
172
+ loginPath,
173
+ extraClearKeys
174
+ },
175
+ sendOtp,
176
+ login,
177
+ logout,
178
+ refresh,
179
+ clearSession,
180
+ isLoggedIn: () => isLoggedIn(cookieKeys),
181
+ getTokenExpiry: () => getTokenExpiry(cookieKeys),
182
+ getSessionProfile: () => getSessionProfile(cookieKeys, permissionsStorageKey)
183
+ };
184
+ }
185
+ var AuthContext = react.createContext(null);
186
+ function defaultMapError(error, phase) {
187
+ if (phase === "verifyOtp") return "Invalid OTP";
188
+ if (phase === "logout") return "Error logging out";
189
+ const err = error;
190
+ const data = err?.response?.data?.data;
191
+ if (data && typeof data === "object" && "identifier" in data) {
192
+ const identifier = data.identifier;
193
+ if (Array.isArray(identifier)) return identifier.join("");
194
+ }
195
+ return "An error occurred";
196
+ }
197
+ function AuthProvider({
198
+ client,
199
+ children,
200
+ onLoginSuccess,
201
+ onLogout,
202
+ mapError = defaultMapError
203
+ }) {
204
+ const [status, setStatus] = react.useState("IDLE");
205
+ const [error, setError] = react.useState(null);
206
+ const [user, setUser] = react.useState(null);
207
+ const signIn = react.useCallback(
208
+ async (payload) => {
209
+ try {
210
+ setStatus("PENDING");
211
+ setError(null);
212
+ const response = await client.sendOtp(payload);
213
+ setStatus("SUCCESS");
214
+ return response;
215
+ } catch (err) {
216
+ const message = mapError(err, "signIn");
217
+ setStatus("ERROR");
218
+ setError(message);
219
+ throw err;
220
+ }
221
+ },
222
+ [client, mapError]
223
+ );
224
+ const verifyOtp = react.useCallback(
225
+ async (payload) => {
226
+ try {
227
+ setStatus("PENDING");
228
+ setError(null);
229
+ const nextUser = await client.login(payload);
230
+ setUser(nextUser);
231
+ setStatus("SUCCESS");
232
+ await onLoginSuccess?.(nextUser);
233
+ return nextUser;
234
+ } catch (err) {
235
+ const message = mapError(err, "verifyOtp");
236
+ setStatus("ERROR");
237
+ setError(message);
238
+ throw err;
239
+ }
240
+ },
241
+ [client, mapError, onLoginSuccess]
242
+ );
243
+ const logout = react.useCallback(async () => {
244
+ try {
245
+ setStatus("PENDING");
246
+ await client.logout();
247
+ setUser(null);
248
+ setStatus("IDLE");
249
+ setError(null);
250
+ await onLogout?.();
251
+ } catch (err) {
252
+ const message = mapError(err, "logout");
253
+ setStatus("ERROR");
254
+ setError(message);
255
+ throw err;
256
+ }
257
+ }, [client, mapError, onLogout]);
258
+ const value = react.useMemo(
259
+ () => ({
260
+ client,
261
+ status,
262
+ error,
263
+ user,
264
+ signIn,
265
+ verifyOtp,
266
+ logout,
267
+ isAuthenticated: client.isLoggedIn()
268
+ }),
269
+ [client, status, error, user, signIn, verifyOtp, logout]
270
+ );
271
+ return /* @__PURE__ */ jsxRuntime.jsx(AuthContext.Provider, { value, children });
272
+ }
273
+ function useAuth() {
274
+ const ctx = react.useContext(AuthContext);
275
+ if (!ctx) {
276
+ throw new Error("useAuth must be used within an AuthProvider");
277
+ }
278
+ return ctx;
279
+ }
280
+ function ProtectedRoute({
281
+ client,
282
+ redirectTo,
283
+ children
284
+ }) {
285
+ const location = reactRouterDom.useLocation();
286
+ const loginPath = redirectTo ?? client.options.loginPath;
287
+ if (!client.isLoggedIn()) {
288
+ return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: loginPath, replace: true, state: { from: location } });
289
+ }
290
+ return children ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }) : /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Outlet, {});
291
+ }
292
+ function GuestRoute({
293
+ client,
294
+ redirectTo = "/",
295
+ children
296
+ }) {
297
+ if (client.isLoggedIn()) {
298
+ return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: redirectTo, replace: true });
299
+ }
300
+ return children ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }) : /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Outlet, {});
301
+ }
302
+ function useAutoLogout({
303
+ client,
304
+ intervalMs = 3e4,
305
+ enabled = true
306
+ }) {
307
+ const loggingOut = react.useRef(false);
308
+ react.useEffect(() => {
309
+ if (!enabled) return;
310
+ const tick = async () => {
311
+ if (!client.isLoggedIn() || loggingOut.current) return;
312
+ const expiry = client.getTokenExpiry();
313
+ if (expiry == null) return;
314
+ const expiryMs = expiry < 1e12 ? expiry * 1e3 : expiry;
315
+ if (Date.now() >= expiryMs) {
316
+ loggingOut.current = true;
317
+ try {
318
+ await client.logout();
319
+ } finally {
320
+ loggingOut.current = false;
321
+ }
322
+ }
323
+ };
324
+ void tick();
325
+ const id = window.setInterval(tick, intervalMs);
326
+ return () => window.clearInterval(id);
327
+ }, [client, intervalMs, enabled]);
328
+ }
329
+ var headerStyle = {
330
+ display: "flex",
331
+ flexDirection: "column",
332
+ alignItems: "center",
333
+ gap: 4,
334
+ marginBottom: 24
335
+ };
336
+ var titleStyle = {
337
+ margin: 0,
338
+ textAlign: "center",
339
+ fontWeight: 600
340
+ };
341
+ var descriptionStyle = {
342
+ margin: 0,
343
+ textAlign: "center"
344
+ };
345
+ var inputStyle = {
346
+ height: 48,
347
+ borderRadius: 6
348
+ };
349
+ var formGapStyle = {
350
+ display: "flex",
351
+ flexDirection: "column",
352
+ gap: 16
353
+ };
354
+ function defaultPlaceholder(mode) {
355
+ if (mode === "mobile") return "Enter Your Mobile Number";
356
+ if (mode === "email") return "Enter Your Email";
357
+ return "Enter Your Email / Phone";
358
+ }
359
+ function validateIdentifier(mode, value) {
360
+ const trimmed = value.trim();
361
+ if (!trimmed) return Promise.reject(new Error("Required"));
362
+ if (mode === "mobile") {
363
+ if (!/^\d{10}$/.test(trimmed)) {
364
+ return Promise.reject(new Error("Enter a valid 10-digit mobile number"));
365
+ }
366
+ } else if (mode === "email") {
367
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmed)) {
368
+ return Promise.reject(new Error("Enter a valid email"));
369
+ }
370
+ } else {
371
+ const isMobile = /^\d{10}$/.test(trimmed);
372
+ const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmed);
373
+ if (!isMobile && !isEmail) {
374
+ return Promise.reject(new Error("Enter a valid email or 10-digit mobile"));
375
+ }
376
+ }
377
+ return Promise.resolve();
378
+ }
379
+ function IdentifierForm({
380
+ onSubmit,
381
+ loading = false,
382
+ mode = "either",
383
+ submitLabel = "Continue",
384
+ title = "Sign in to Indus Action",
385
+ description = "Please Enter Your Email / Phone",
386
+ placeholder,
387
+ initialIdentifier = "",
388
+ label = null
389
+ }) {
390
+ const [form] = antd.Form.useForm();
391
+ const inputPlaceholder = placeholder ?? defaultPlaceholder(mode);
392
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: formGapStyle, children: [
393
+ title || description ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyle, children: [
394
+ title ? /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Title, { level: 3, style: titleStyle, children: title }) : null,
395
+ description ? /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Paragraph, { type: "secondary", style: descriptionStyle, children: description }) : null
396
+ ] }) : null,
397
+ /* @__PURE__ */ jsxRuntime.jsxs(
398
+ antd.Form,
399
+ {
400
+ form,
401
+ layout: "vertical",
402
+ initialValues: { identifier: initialIdentifier },
403
+ onFinish: onSubmit,
404
+ requiredMark: false,
405
+ style: { width: "100%" },
406
+ children: [
407
+ /* @__PURE__ */ jsxRuntime.jsx(
408
+ antd.Form.Item,
409
+ {
410
+ name: "identifier",
411
+ label: label ?? void 0,
412
+ rules: [
413
+ {
414
+ validator: async (_, value) => validateIdentifier(mode, value ?? "")
415
+ }
416
+ ],
417
+ style: { marginBottom: 16 },
418
+ children: /* @__PURE__ */ jsxRuntime.jsx(
419
+ antd.Input,
420
+ {
421
+ size: "large",
422
+ placeholder: inputPlaceholder,
423
+ autoComplete: mode === "mobile" ? "tel" : "username",
424
+ inputMode: mode === "mobile" ? "numeric" : "text",
425
+ style: inputStyle
426
+ }
427
+ )
428
+ }
429
+ ),
430
+ /* @__PURE__ */ jsxRuntime.jsx(
431
+ antd.Button,
432
+ {
433
+ type: "primary",
434
+ htmlType: "submit",
435
+ loading,
436
+ block: true,
437
+ size: "large",
438
+ style: { height: 48, borderRadius: 6 },
439
+ children: submitLabel
440
+ }
441
+ )
442
+ ]
443
+ }
444
+ )
445
+ ] });
446
+ }
447
+ function OtpForm({
448
+ onSubmit,
449
+ onResend,
450
+ loading = false,
451
+ resendLoading = false,
452
+ length = 6,
453
+ title = "Check your email / phone for a code",
454
+ description = "Please enter OTP to continue to your account.",
455
+ submitLabel = "Continue",
456
+ label = null,
457
+ resendSeconds = 120
458
+ }) {
459
+ const [form] = antd.Form.useForm();
460
+ const [secondsLeft, setSecondsLeft] = react.useState(resendSeconds);
461
+ react.useEffect(() => {
462
+ if (secondsLeft <= 0) return;
463
+ const id = window.setTimeout(() => setSecondsLeft((s) => s - 1), 1e3);
464
+ return () => window.clearTimeout(id);
465
+ }, [secondsLeft]);
466
+ const handleResend = async () => {
467
+ if (!onResend || secondsLeft > 0) return;
468
+ await onResend();
469
+ setSecondsLeft(resendSeconds);
470
+ };
471
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: formGapStyle, children: [
472
+ title || description ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyle, children: [
473
+ title ? /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Title, { level: 3, style: titleStyle, children: title }) : null,
474
+ description ? /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Paragraph, { type: "secondary", style: descriptionStyle, children: description }) : null
475
+ ] }) : null,
476
+ /* @__PURE__ */ jsxRuntime.jsxs(
477
+ antd.Form,
478
+ {
479
+ form,
480
+ layout: "vertical",
481
+ onFinish: onSubmit,
482
+ requiredMark: false,
483
+ style: { width: "100%" },
484
+ children: [
485
+ /* @__PURE__ */ jsxRuntime.jsx(
486
+ antd.Form.Item,
487
+ {
488
+ name: "otp",
489
+ label: label ?? void 0,
490
+ rules: [
491
+ { required: true, message: "Enter OTP" },
492
+ {
493
+ len: length,
494
+ message: `OTP must be ${length} digits`
495
+ }
496
+ ],
497
+ style: { marginBottom: 16 },
498
+ children: /* @__PURE__ */ jsxRuntime.jsx(
499
+ antd.Input.OTP,
500
+ {
501
+ length,
502
+ size: "large",
503
+ style: { display: "flex", width: "100%" }
504
+ }
505
+ )
506
+ }
507
+ ),
508
+ /* @__PURE__ */ jsxRuntime.jsx(
509
+ antd.Button,
510
+ {
511
+ type: "primary",
512
+ htmlType: "submit",
513
+ loading,
514
+ block: true,
515
+ size: "large",
516
+ style: { height: 48, borderRadius: 6 },
517
+ children: submitLabel
518
+ }
519
+ )
520
+ ]
521
+ }
522
+ ),
523
+ onResend ? /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Paragraph, { style: { marginTop: 8, textAlign: "center" }, children: secondsLeft > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(antd.Typography.Text, { type: "secondary", children: [
524
+ "Resend OTP in ",
525
+ secondsLeft,
526
+ "s"
527
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
528
+ antd.Button,
529
+ {
530
+ type: "link",
531
+ loading: resendLoading,
532
+ onClick: () => void handleResend(),
533
+ children: "Resend OTP"
534
+ }
535
+ ) }) : null
536
+ ] });
537
+ }
538
+
539
+ exports.AuthProvider = AuthProvider;
540
+ exports.DEFAULT_AUTH_PATHS = DEFAULT_AUTH_PATHS;
541
+ exports.GuestRoute = GuestRoute;
542
+ exports.IdentifierForm = IdentifierForm;
543
+ exports.MOBILE_SEND_OTP_PATH = MOBILE_SEND_OTP_PATH;
544
+ exports.OtpForm = OtpForm;
545
+ exports.ProtectedRoute = ProtectedRoute;
546
+ exports.authCookieKeyList = authCookieKeyList;
547
+ exports.buildCookieKeys = buildCookieKeys;
548
+ exports.clearAuthStorage = clearAuthStorage;
549
+ exports.createAuthClient = createAuthClient;
550
+ exports.getSessionProfile = getSessionProfile;
551
+ exports.getTokenExpiry = getTokenExpiry;
552
+ exports.isLoggedIn = isLoggedIn;
553
+ exports.joinPath = joinPath;
554
+ exports.persistSessionProfile = persistSessionProfile;
555
+ exports.useAuth = useAuth;
556
+ exports.useAutoLogout = useAutoLogout;
557
+ //# sourceMappingURL=index.cjs.map
558
+ //# sourceMappingURL=index.cjs.map