@mesob/auth-react 0.4.7 → 0.5.2
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/{chunk-5E3XN6SW.js → chunk-22WQJ3NP.js} +4 -4
- package/dist/{chunk-ECF6S2Y2.js → chunk-24E7XFGP.js} +2 -2
- package/dist/{chunk-AWSAC7RT.js → chunk-2XIZ27DU.js} +4 -1
- package/dist/{chunk-AWSAC7RT.js.map → chunk-2XIZ27DU.js.map} +1 -1
- package/dist/{chunk-DG6GRTPG.js → chunk-4CUQIZ2Q.js} +2 -2
- package/dist/{chunk-5BFG47VF.js → chunk-55WFD2Y2.js} +4 -4
- package/dist/{chunk-GVEBIL3O.js → chunk-6L4K26KM.js} +2 -2
- package/dist/{chunk-MWMSZVH3.js → chunk-BIP5XEDV.js} +4 -4
- package/dist/{chunk-YFQNNSSC.js → chunk-C34HWZA5.js} +2 -2
- package/dist/{chunk-T34HJRUW.js → chunk-CDX5V66G.js} +3 -3
- package/dist/{chunk-V6ZHX4LT.js → chunk-DJWX4ENN.js} +2 -2
- package/dist/chunk-G2XRGSQE.js +22 -0
- package/dist/chunk-G2XRGSQE.js.map +1 -0
- package/dist/{chunk-6THPM5LB.js → chunk-GXWBGB6G.js} +4 -4
- package/dist/{chunk-6IEX2RLA.js → chunk-HVAYVDIM.js} +3 -3
- package/dist/{chunk-5HAABEAS.js → chunk-J4Q7RYYY.js} +2 -2
- package/dist/{chunk-OXUOGOG3.js → chunk-JNVJWNJT.js} +87 -20
- package/dist/chunk-JNVJWNJT.js.map +1 -0
- package/dist/{chunk-RMJNENJB.js → chunk-K2523VB5.js} +2 -2
- package/dist/{chunk-5AEV7RAN.js → chunk-KWL6FBP7.js} +3 -3
- package/dist/{chunk-IQNQGPIT.js → chunk-LJIZEECR.js} +4 -4
- package/dist/{chunk-SGDXNT7M.js → chunk-LQX2365R.js} +3 -3
- package/dist/{chunk-MVVAPYUD.js → chunk-NLK2J4UG.js} +2 -2
- package/dist/{chunk-ZZ6D4KE4.js → chunk-NUCDZRXS.js} +2 -2
- package/dist/{chunk-EQWOGD4F.js → chunk-OPSVSBOB.js} +2 -2
- package/dist/{chunk-5SDS2E3F.js → chunk-PCBJBXEK.js} +2 -2
- package/dist/{chunk-VVKXFEAN.js → chunk-PFUTYTDB.js} +4 -4
- package/dist/{chunk-WY2JJNZW.js → chunk-QHHVGLHT.js} +2 -2
- package/dist/{chunk-W3D4HG5W.js → chunk-QJOBPOTR.js} +3 -3
- package/dist/{chunk-MQI6Q2S4.js → chunk-R6ME7P5U.js} +147 -4
- package/dist/chunk-R6ME7P5U.js.map +1 -0
- package/dist/{chunk-N4JFMKGK.js → chunk-RPKO5EQ5.js} +5 -5
- package/dist/{chunk-CP4TTRV4.js → chunk-RZFCA4YG.js} +2 -2
- package/dist/{chunk-7CLKBH5Z.js → chunk-S772WZD7.js} +3 -3
- package/dist/{chunk-73ZNGEWU.js → chunk-SBSAOWP5.js} +5 -5
- package/dist/{chunk-H7JRQFFI.js → chunk-TEARMXTQ.js} +3 -3
- package/dist/{chunk-UY55LEIG.js → chunk-UN6YBSRS.js} +2 -2
- package/dist/{chunk-TEHMLZFI.js → chunk-UOQGT574.js} +3 -3
- package/dist/{chunk-Y4AH5JY4.js → chunk-VVFBMIIB.js} +92 -16
- package/dist/chunk-VVFBMIIB.js.map +1 -0
- package/dist/{chunk-TLQMK2QF.js → chunk-WBRGSWKX.js} +4 -4
- package/dist/{chunk-Z34NJZRL.js → chunk-WFHQTVY6.js} +3 -3
- package/dist/{chunk-X2BHF4KC.js → chunk-WTAKMSWN.js} +2 -2
- package/dist/{chunk-UGQP733V.js → chunk-XGE6G3EK.js} +2 -2
- package/dist/{chunk-4ABXALRN.js → chunk-XL2DCDFZ.js} +2 -2
- package/dist/{chunk-EPEXIGKB.js → chunk-XUV6CYTY.js} +2 -2
- package/dist/{chunk-H5PUZDNU.js → chunk-YQLGGIE4.js} +4 -4
- package/dist/{chunk-4X3CJHKR.js → chunk-ZGDN6MQA.js} +3 -3
- package/dist/{chunk-4NUO6F3J.js → chunk-ZMJUIRZ6.js} +2 -2
- package/dist/components/auth/countdown.js +3 -3
- package/dist/components/auth/forgot-password.js +3 -3
- package/dist/components/auth/reset-password-form.js +3 -3
- package/dist/components/auth/set-password.js +3 -3
- package/dist/components/auth/sign-in.js +3 -3
- package/dist/components/auth/sign-up.js +3 -3
- package/dist/components/auth/verification-form.js +4 -4
- package/dist/components/auth/verify-email.js +5 -5
- package/dist/components/auth/verify-phone.js +5 -5
- package/dist/components/authorization/deny.js +2 -2
- package/dist/components/authorization/grant.js +2 -2
- package/dist/components/error-boundary.d.ts +1 -1
- package/dist/components/iam/domains-page.js +6 -6
- package/dist/components/iam/iam-guard.js +3 -3
- package/dist/components/iam/permission-selector.js +2 -2
- package/dist/components/iam/permissions-page.js +4 -4
- package/dist/components/iam/permissions.js +2 -2
- package/dist/components/iam/role-detail-layout.js +2 -2
- package/dist/components/iam/role-detail-page.js +4 -4
- package/dist/components/iam/role-permissions-page.js +5 -5
- package/dist/components/iam/roles-page.js +6 -7
- package/dist/components/iam/roles.js +2 -2
- package/dist/components/iam/sessions-page.js +6 -6
- package/dist/components/iam/sessions.js +2 -2
- package/dist/components/iam/tenants-page.js +6 -6
- package/dist/components/iam/tenants.js +2 -2
- package/dist/components/iam/users-page.js +7 -7
- package/dist/components/iam/users.js +2 -2
- package/dist/components/profile/account.js +2 -2
- package/dist/components/profile/change-email-form.js +8 -8
- package/dist/components/profile/change-password-form.js +2 -2
- package/dist/components/profile/change-phone-form.js +8 -8
- package/dist/components/profile/otp-verification-modal.js +5 -5
- package/dist/components/profile/profile-layout.js +3 -3
- package/dist/components/profile/request-change-email-form.js +2 -2
- package/dist/components/profile/request-change-phone-form.js +2 -2
- package/dist/components/profile/security.js +13 -13
- package/dist/components/profile/verify-change-email-form.js +6 -6
- package/dist/components/profile/verify-change-phone-form.js +6 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +975 -63
- package/dist/index.js.map +1 -1
- package/dist/pages/__import_guard_probe.d.ts +4 -0
- package/dist/pages/auth/forgot-password.js +1 -8
- package/dist/pages/auth/forgot-password.js.map +1 -1
- package/dist/pages/auth/layout.js +6 -4
- package/dist/pages/auth/layout.js.map +1 -1
- package/dist/pages/auth/reset-password.js +1 -8
- package/dist/pages/auth/reset-password.js.map +1 -1
- package/dist/pages/auth/set-password.js +1 -9
- package/dist/pages/auth/set-password.js.map +1 -1
- package/dist/pages/auth/sign-in.js +1 -9
- package/dist/pages/auth/sign-in.js.map +1 -1
- package/dist/pages/auth/sign-up.js +1 -8
- package/dist/pages/auth/sign-up.js.map +1 -1
- package/dist/pages/auth/verify-email.js +1 -10
- package/dist/pages/auth/verify-email.js.map +1 -1
- package/dist/pages/auth/verify-phone.js +1 -10
- package/dist/pages/auth/verify-phone.js.map +1 -1
- package/dist/pages/iam/domains.d.ts +1 -1
- package/dist/pages/iam/permissions.d.ts +1 -1
- package/dist/pages/iam/permissions.js +3 -7
- package/dist/pages/iam/permissions.js.map +1 -1
- package/dist/pages/iam/role-detail-layout.js +1 -5
- package/dist/pages/iam/role-detail-layout.js.map +1 -1
- package/dist/pages/iam/role-detail.js +1 -7
- package/dist/pages/iam/role-detail.js.map +1 -1
- package/dist/pages/iam/role-permissions.js +1 -8
- package/dist/pages/iam/role-permissions.js.map +1 -1
- package/dist/pages/iam/role-users.js +1 -13
- package/dist/pages/iam/role-users.js.map +1 -1
- package/dist/pages/iam/roles.d.ts +1 -1
- package/dist/pages/iam/roles.js +3 -11
- package/dist/pages/iam/roles.js.map +1 -1
- package/dist/pages/iam/sessions.d.ts +1 -1
- package/dist/pages/iam/sessions.js +3 -9
- package/dist/pages/iam/sessions.js.map +1 -1
- package/dist/pages/iam/tenant-detail.js +1 -8
- package/dist/pages/iam/tenant-detail.js.map +1 -1
- package/dist/pages/iam/tenants/tenant-selector.js +3 -3
- package/dist/pages/iam/tenants.d.ts +1 -1
- package/dist/pages/iam/tenants.js +3 -10
- package/dist/pages/iam/tenants.js.map +1 -1
- package/dist/pages/iam/user-activity.js +1 -12
- package/dist/pages/iam/user-activity.js.map +1 -1
- package/dist/pages/iam/user-detail-layout.js +1 -7
- package/dist/pages/iam/user-detail-layout.js.map +1 -1
- package/dist/pages/iam/user-detail.js +1 -7
- package/dist/pages/iam/user-detail.js.map +1 -1
- package/dist/pages/iam/users/user-selector.js +149 -7
- package/dist/pages/iam/users/user-selector.js.map +1 -1
- package/dist/pages/iam/users.d.ts +1 -1
- package/dist/pages/iam/users.js +3 -11
- package/dist/pages/iam/users.js.map +1 -1
- package/dist/pages/profile/account.js +2 -5
- package/dist/pages/profile/account.js.map +1 -1
- package/dist/pages/profile/layout.d.ts +1 -1
- package/dist/pages/profile/layout.js +3 -5
- package/dist/pages/profile/layout.js.map +1 -1
- package/dist/pages/profile/security.js +2 -16
- package/dist/pages/profile/security.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/utils/safe-redirect.d.ts +2 -0
- package/package.json +4 -4
- package/dist/chunk-GBDNBY6K.js +0 -153
- package/dist/chunk-GBDNBY6K.js.map +0 -1
- package/dist/chunk-MQI6Q2S4.js.map +0 -1
- package/dist/chunk-NFGFJPCX.js +0 -313
- package/dist/chunk-NFGFJPCX.js.map +0 -1
- package/dist/chunk-NJMNRSJH.js +0 -83
- package/dist/chunk-NJMNRSJH.js.map +0 -1
- package/dist/chunk-OXUOGOG3.js.map +0 -1
- package/dist/chunk-QPEUVMSP.js +0 -149
- package/dist/chunk-QPEUVMSP.js.map +0 -1
- package/dist/chunk-RCQTWNAG.js +0 -150
- package/dist/chunk-RCQTWNAG.js.map +0 -1
- package/dist/chunk-SGUROG23.js +0 -356
- package/dist/chunk-SGUROG23.js.map +0 -1
- package/dist/chunk-X6EUQZSZ.js +0 -81
- package/dist/chunk-X6EUQZSZ.js.map +0 -1
- package/dist/chunk-Y4AH5JY4.js.map +0 -1
- /package/dist/{chunk-5E3XN6SW.js.map → chunk-22WQJ3NP.js.map} +0 -0
- /package/dist/{chunk-ECF6S2Y2.js.map → chunk-24E7XFGP.js.map} +0 -0
- /package/dist/{chunk-DG6GRTPG.js.map → chunk-4CUQIZ2Q.js.map} +0 -0
- /package/dist/{chunk-5BFG47VF.js.map → chunk-55WFD2Y2.js.map} +0 -0
- /package/dist/{chunk-GVEBIL3O.js.map → chunk-6L4K26KM.js.map} +0 -0
- /package/dist/{chunk-MWMSZVH3.js.map → chunk-BIP5XEDV.js.map} +0 -0
- /package/dist/{chunk-YFQNNSSC.js.map → chunk-C34HWZA5.js.map} +0 -0
- /package/dist/{chunk-T34HJRUW.js.map → chunk-CDX5V66G.js.map} +0 -0
- /package/dist/{chunk-V6ZHX4LT.js.map → chunk-DJWX4ENN.js.map} +0 -0
- /package/dist/{chunk-6THPM5LB.js.map → chunk-GXWBGB6G.js.map} +0 -0
- /package/dist/{chunk-6IEX2RLA.js.map → chunk-HVAYVDIM.js.map} +0 -0
- /package/dist/{chunk-5HAABEAS.js.map → chunk-J4Q7RYYY.js.map} +0 -0
- /package/dist/{chunk-RMJNENJB.js.map → chunk-K2523VB5.js.map} +0 -0
- /package/dist/{chunk-5AEV7RAN.js.map → chunk-KWL6FBP7.js.map} +0 -0
- /package/dist/{chunk-IQNQGPIT.js.map → chunk-LJIZEECR.js.map} +0 -0
- /package/dist/{chunk-SGDXNT7M.js.map → chunk-LQX2365R.js.map} +0 -0
- /package/dist/{chunk-MVVAPYUD.js.map → chunk-NLK2J4UG.js.map} +0 -0
- /package/dist/{chunk-ZZ6D4KE4.js.map → chunk-NUCDZRXS.js.map} +0 -0
- /package/dist/{chunk-EQWOGD4F.js.map → chunk-OPSVSBOB.js.map} +0 -0
- /package/dist/{chunk-5SDS2E3F.js.map → chunk-PCBJBXEK.js.map} +0 -0
- /package/dist/{chunk-VVKXFEAN.js.map → chunk-PFUTYTDB.js.map} +0 -0
- /package/dist/{chunk-WY2JJNZW.js.map → chunk-QHHVGLHT.js.map} +0 -0
- /package/dist/{chunk-W3D4HG5W.js.map → chunk-QJOBPOTR.js.map} +0 -0
- /package/dist/{chunk-N4JFMKGK.js.map → chunk-RPKO5EQ5.js.map} +0 -0
- /package/dist/{chunk-CP4TTRV4.js.map → chunk-RZFCA4YG.js.map} +0 -0
- /package/dist/{chunk-7CLKBH5Z.js.map → chunk-S772WZD7.js.map} +0 -0
- /package/dist/{chunk-73ZNGEWU.js.map → chunk-SBSAOWP5.js.map} +0 -0
- /package/dist/{chunk-H7JRQFFI.js.map → chunk-TEARMXTQ.js.map} +0 -0
- /package/dist/{chunk-UY55LEIG.js.map → chunk-UN6YBSRS.js.map} +0 -0
- /package/dist/{chunk-TEHMLZFI.js.map → chunk-UOQGT574.js.map} +0 -0
- /package/dist/{chunk-TLQMK2QF.js.map → chunk-WBRGSWKX.js.map} +0 -0
- /package/dist/{chunk-Z34NJZRL.js.map → chunk-WFHQTVY6.js.map} +0 -0
- /package/dist/{chunk-X2BHF4KC.js.map → chunk-WTAKMSWN.js.map} +0 -0
- /package/dist/{chunk-UGQP733V.js.map → chunk-XGE6G3EK.js.map} +0 -0
- /package/dist/{chunk-4ABXALRN.js.map → chunk-XL2DCDFZ.js.map} +0 -0
- /package/dist/{chunk-EPEXIGKB.js.map → chunk-XUV6CYTY.js.map} +0 -0
- /package/dist/{chunk-H5PUZDNU.js.map → chunk-YQLGGIE4.js.map} +0 -0
- /package/dist/{chunk-4X3CJHKR.js.map → chunk-ZGDN6MQA.js.map} +0 -0
- /package/dist/{chunk-4NUO6F3J.js.map → chunk-ZMJUIRZ6.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VerificationForm
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WFHQTVY6.js";
|
|
4
4
|
import {
|
|
5
5
|
handleError
|
|
6
6
|
} from "./chunk-RRLFPSSM.js";
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
} from "./chunk-DPH2PHK3.js";
|
|
10
10
|
import {
|
|
11
11
|
useTranslator
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XUV6CYTY.js";
|
|
13
13
|
import {
|
|
14
14
|
useApi,
|
|
15
15
|
useConfig
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-2XIZ27DU.js";
|
|
17
17
|
|
|
18
18
|
// src/components/auth/verify-phone.tsx
|
|
19
19
|
import { Alert, AlertDescription, AlertTitle } from "@mesob/ui/components";
|
|
@@ -185,4 +185,4 @@ var VerifyPhone = ({
|
|
|
185
185
|
export {
|
|
186
186
|
VerifyPhone
|
|
187
187
|
};
|
|
188
|
-
//# sourceMappingURL=chunk-
|
|
188
|
+
//# sourceMappingURL=chunk-22WQJ3NP.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
Link,
|
|
6
6
|
authApi$
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QJOBPOTR.js";
|
|
8
8
|
|
|
9
9
|
// src/pages/iam/users/_components/user-card.tsx
|
|
10
10
|
import {
|
|
@@ -482,4 +482,4 @@ export {
|
|
|
482
482
|
UserForm,
|
|
483
483
|
UserCard
|
|
484
484
|
};
|
|
485
|
-
//# sourceMappingURL=chunk-
|
|
485
|
+
//# sourceMappingURL=chunk-24E7XFGP.js.map
|
|
@@ -49,6 +49,9 @@ var defaultAuthClientConfig = {
|
|
|
49
49
|
enablePasswordReset: true,
|
|
50
50
|
enableEmailSignup: true,
|
|
51
51
|
enablePhoneSignup: true,
|
|
52
|
+
enableEmailSignIn: true,
|
|
53
|
+
enablePhoneSignIn: true,
|
|
54
|
+
allowedSignupEmailDomains: [],
|
|
52
55
|
enableSocialSignup: false,
|
|
53
56
|
socialProviders: []
|
|
54
57
|
},
|
|
@@ -288,4 +291,4 @@ export {
|
|
|
288
291
|
useHasAuthCookie,
|
|
289
292
|
MesobAuthProvider
|
|
290
293
|
};
|
|
291
|
-
//# sourceMappingURL=chunk-
|
|
294
|
+
//# sourceMappingURL=chunk-2XIZ27DU.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/cookie.ts","../src/provider.tsx","../src/lib/translations.ts","../src/types.ts","../src/utils/custom-fetch.ts"],"sourcesContent":["import type { AuthClientConfig } from '../types';\n\nconst isProduction =\n typeof process !== 'undefined' && process.env.NODE_ENV === 'production';\n\nexport const getSessionCookieName = (config: AuthClientConfig): string => {\n const prefix = config.cookiePrefix || '';\n const baseName = 'session_token';\n if (prefix) {\n return `${prefix}_${baseName}`;\n }\n return isProduction ? '__Host-session_token' : baseName;\n};\n","'use client';\n\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { deepmerge } from 'deepmerge-ts';\nimport createFetchClient from 'openapi-fetch';\nimport createClient from 'openapi-react-query';\nimport type { ReactNode } from 'react';\nimport { createContext, useContext, useMemo, useState } from 'react';\nimport type { paths } from './data/openapi';\nimport { createTranslator } from './lib/translations';\nimport {\n type AuthClientConfig,\n type AuthResponse,\n defaultAuthClientConfig,\n type Session,\n type User,\n} from './types';\nimport { getSessionCookieName } from './utils/cookie';\nimport { createCustomFetch } from './utils/custom-fetch';\n\n// biome-ignore lint/suspicious/noExplicitAny: OpenAPI hooks type\ntype OpenApiHooks = any;\n\n// --- Utility: Check if running on server ---\nfunction isServer(): boolean {\n return typeof document === 'undefined';\n}\n\n/**\n * @deprecated Cookie is httpOnly and cannot be read client-side.\n * Use `useSession().isAuthenticated` instead.\n * This function always returns false on client.\n */\nexport function hasAuthCookie(_cookieName: string): boolean {\n // Cookie is httpOnly, can't check client-side\n // Always return false - use useSession() for auth status\n return false;\n}\n\n// --- Types ---\nexport type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated';\n\ntype AuthState = {\n user: User | null;\n session: Session | null;\n status: AuthStatus;\n error: Error | null;\n};\n\ntype SessionContextValue = AuthState & {\n isLoading: boolean;\n isAuthenticated: boolean;\n refresh: () => Promise<void>;\n signOut: () => Promise<void>;\n};\n\ntype ApiContextValue = {\n hooks: OpenApiHooks;\n setAuth: (auth: AuthResponse) => void;\n clearAuth: () => void;\n refresh: () => Promise<void>;\n};\n\ntype ConfigContextValue = {\n config: AuthClientConfig;\n cookieName: string;\n t: (key: string, params?: Record<string, string | number>) => string;\n};\n\nconst SessionContext = createContext<SessionContextValue | null>(null);\nconst ApiContext = createContext<ApiContextValue | null>(null);\nconst ConfigContext = createContext<ConfigContextValue | null>(null);\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n },\n },\n});\n\n// --- Hooks ---\n\n/**\n * Get session state including user, session, and auth status.\n * - `status`: 'loading' | 'authenticated' | 'unauthenticated'\n * - `isLoading`: true while fetching session\n * - `isAuthenticated`: true if user and session exist\n */\nexport function useSession(): SessionContextValue {\n const context = useContext(SessionContext);\n if (!context) {\n throw new Error('useSession must be used within MesobAuthProvider');\n }\n return context;\n}\n\nexport function useApi(): ApiContextValue {\n const context = useContext(ApiContext);\n if (!context) {\n throw new Error('useApi must be used within MesobAuthProvider');\n }\n return context;\n}\n\nexport function useConfig(): ConfigContextValue {\n const context = useContext(ConfigContext);\n if (!context) {\n throw new Error('useConfig must be used within MesobAuthProvider');\n }\n return context;\n}\n\n/**\n * @deprecated Cookie is httpOnly, can't be checked client-side.\n * Use `useSession().isAuthenticated` instead.\n */\nexport function useHasAuthCookie(): boolean {\n const { status } = useSession();\n return status === 'authenticated' || status === 'loading';\n}\n\n// --- Provider ---\n\ntype MesobAuthProviderProps = {\n config: AuthClientConfig;\n children: ReactNode;\n};\n\nexport function MesobAuthProvider({\n config,\n children,\n}: MesobAuthProviderProps) {\n const mergedConfig = useMemo(\n () =>\n deepmerge(\n { ...defaultAuthClientConfig } as Partial<AuthClientConfig>,\n config,\n ) as AuthClientConfig,\n [config],\n );\n\n const api = useMemo(\n () =>\n createFetchClient<paths>({\n baseUrl: mergedConfig.baseURL,\n fetch: createCustomFetch(mergedConfig),\n }),\n [mergedConfig],\n );\n\n const hooks = useMemo(() => createClient(api), [api]);\n const cookieName = useMemo(\n () => getSessionCookieName(mergedConfig),\n [mergedConfig],\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <AuthStateProvider\n config={mergedConfig}\n hooks={hooks}\n cookieName={cookieName}\n >\n {children}\n </AuthStateProvider>\n </QueryClientProvider>\n );\n}\n\ntype AuthStateProviderProps = {\n config: AuthClientConfig;\n hooks: OpenApiHooks;\n cookieName: string;\n children: ReactNode;\n};\n\nfunction AuthStateProvider({\n config,\n hooks,\n cookieName,\n children,\n}: AuthStateProviderProps) {\n // Manual override for sign-out / sign-in\n const [override, setOverride] = useState<AuthState | null>(null);\n\n // Always fetch session - cookie is httpOnly, can't check client-side\n // Server will read the cookie and return user/session if valid\n const {\n data: sessionData,\n isLoading,\n isFetched,\n error: sessionError,\n refetch,\n } = hooks.useQuery(\n 'get',\n '/session',\n {},\n {\n enabled: !(override || isServer()),\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n retry: false,\n gcTime: 0,\n staleTime: 0,\n },\n );\n\n // Derive state directly - no useEffect\n const user = override?.user ?? sessionData?.user ?? null;\n const session = override?.session ?? sessionData?.session ?? null;\n const error = override?.error ?? (sessionError as Error | null);\n\n // Check error status code\n const errorStatus = (() => {\n if (!sessionError) {\n return null;\n }\n const err = sessionError as { status?: number };\n return err.status ?? null;\n })();\n\n // Check if error is a network/connection error\n const isNetworkError = (() => {\n if (!sessionError) {\n return false;\n }\n const error = sessionError as Error & { cause?: unknown; data?: unknown };\n const errorMessage =\n error.message || String(error) || JSON.stringify(error);\n // Network errors: TypeError, DOMException, or fetch failures\n if (\n error instanceof TypeError ||\n error instanceof DOMException ||\n error.name === 'TypeError' ||\n errorMessage.includes('Failed to fetch') ||\n errorMessage.includes('ERR_CONNECTION_REFUSED') ||\n errorMessage.includes('NetworkError') ||\n errorMessage.includes('Network request failed') ||\n errorMessage.includes('fetch failed')\n ) {\n return true;\n }\n // Check error cause\n if (error.cause) {\n const causeStr = String(error.cause);\n if (\n causeStr.includes('Failed to fetch') ||\n causeStr.includes('ERR_CONNECTION_REFUSED') ||\n causeStr.includes('NetworkError')\n ) {\n return true;\n }\n }\n return false;\n })();\n\n // Compute status\n // biome-ignore lint: Status determination requires multiple checks\n const status: AuthStatus = (() => {\n if (override) {\n return override.status;\n }\n if (isServer()) {\n return 'loading';\n }\n if (user && session) {\n return 'authenticated';\n }\n // Check for network errors or auth errors first - allow auth page to show\n if (isNetworkError || errorStatus === 401) {\n return 'unauthenticated';\n }\n // If we have an error but it's not a network error, still check loading state\n if (sessionError && !isNetworkError && errorStatus !== 401) {\n if (errorStatus && errorStatus >= 500) {\n return 'authenticated';\n }\n // Other errors mean unauthenticated\n if (isFetched) {\n return 'unauthenticated';\n }\n }\n if (isLoading || !isFetched) {\n return 'loading';\n }\n if (isFetched && !user && !session) {\n return 'unauthenticated';\n }\n return 'unauthenticated';\n })();\n\n const signOutMutation = hooks.useMutation('post', '/sign-out');\n const t = createTranslator(config.messages || {});\n\n const setAuth = (auth: AuthResponse) => {\n setOverride({\n user: auth.user,\n session: auth.session,\n status: 'authenticated',\n error: null,\n });\n };\n\n const clearAuth = () => {\n setOverride({\n user: null,\n session: null,\n status: 'unauthenticated',\n error: null,\n });\n };\n\n const refresh = async () => {\n setOverride(null);\n await refetch();\n };\n\n const signOut = async () => {\n await signOutMutation.mutateAsync({});\n clearAuth();\n\n const redirectUrl = config.navigation?.defaultRedirectUrl || '/';\n\n if (config.navigation?.onNavigate) {\n config.navigation.onNavigate(redirectUrl);\n } else if (typeof window !== 'undefined') {\n window.location.href = redirectUrl;\n }\n };\n\n return (\n <ConfigContext.Provider value={{ config, cookieName, t }}>\n <ApiContext.Provider value={{ hooks, setAuth, clearAuth, refresh }}>\n <SessionContext.Provider\n value={{\n user,\n session,\n status,\n error,\n isLoading: status === 'loading',\n isAuthenticated: status === 'authenticated',\n refresh,\n signOut,\n }}\n >\n {children}\n </SessionContext.Provider>\n </ApiContext.Provider>\n </ConfigContext.Provider>\n );\n}\n","type Messages = Record<string, unknown>;\n\nexport function createTranslator(messages: Messages, namespace?: string) {\n return (key: string, params?: Record<string, string | number>): string => {\n const fullKey = namespace ? `${namespace}.${key}` : key;\n const keys = fullKey.split('.');\n\n let value: unknown = messages;\n for (const k of keys) {\n if (value && typeof value === 'object' && value !== null) {\n value = (value as Record<string, unknown>)[k];\n } else {\n return fullKey;\n }\n }\n\n if (typeof value !== 'string') {\n return fullKey;\n }\n\n // Simple parameter replacement\n if (params) {\n return value.replace(/\\{(\\w+)\\}/g, (_, param) =>\n String(params[param] ?? `{${param}}`),\n );\n }\n\n return value;\n };\n}\n","import type { PermissionTree } from '@mesob/common';\n\nexport type UIConfig = {\n logo: React.ReactNode;\n name: React.ReactNode;\n logoImage?: string;\n};\n\nexport type FeaturesConfig = {\n enableSignup?: boolean;\n enablePasswordReset?: boolean;\n enableEmailSignup?: boolean;\n enablePhoneSignup?: boolean;\n enableSocialSignup?: boolean;\n socialProviders?: string[];\n};\n\nexport type TenantConfig = {\n enabled: boolean;\n tenantId: string;\n};\n\nexport type NavigationConfig = {\n locale?: string;\n defaultRedirectUrl?: string;\n onNavigate?: (path: string) => void;\n linkComponent?: React.ComponentType<\n React.ComponentProps<'a'> & { href: string }\n >;\n links?: {\n signIn?: string;\n signUp?: string;\n forgotPassword?: string;\n setPassword?: string;\n };\n};\n\nexport type AuthClientConfig = {\n baseURL: string;\n ui: UIConfig;\n features?: FeaturesConfig;\n tenant?: TenantConfig;\n permissions?: PermissionTree;\n navigation?: NavigationConfig;\n messages?: Record<string, unknown>;\n cookiePrefix?: string;\n phoneRegex?: RegExp | string;\n /** Default userType filter for users list (e.g. 'employee'). Omit or 'all' to show all. */\n defaultUserType?: string;\n};\n\ntype DefaultAuthClientConfig = {\n readonly features: {\n readonly enableSignup: true;\n readonly enablePasswordReset: true;\n readonly enableEmailSignup: true;\n readonly enablePhoneSignup: true;\n readonly enableSocialSignup: false;\n readonly socialProviders: [];\n };\n readonly navigation: {\n readonly locale: 'en';\n };\n readonly cookiePrefix: 'msb';\n readonly phoneRegex: RegExp;\n};\n\nexport const defaultAuthClientConfig: DefaultAuthClientConfig = {\n features: {\n enableSignup: true,\n enablePasswordReset: true,\n enableEmailSignup: true,\n enablePhoneSignup: true,\n enableSocialSignup: false,\n socialProviders: [],\n },\n navigation: {\n locale: 'en',\n },\n cookiePrefix: 'msb',\n phoneRegex: /^(\\+2519|\\+2517|2519|2517|09|07)\\d{8}$/,\n} as const;\n\nexport type User = {\n id: string;\n tenantId: string;\n fullName: string;\n email: string | null;\n phone: string | null;\n handle?: string;\n image: string | null;\n emailVerified: boolean;\n phoneVerified: boolean;\n lastSignInAt?: string | null;\n /** Role IDs */\n roles?: string[] | null;\n roleCodes?: string[] | null;\n permissions?: string[] | null;\n};\n\nexport type Session = {\n id?: string;\n expiresAt: string;\n createdAt?: string;\n userAgent?: string | null;\n ip?: string | null;\n};\n\nexport type AuthResponse = {\n user: User;\n session: Session;\n sessionToken?: string;\n sessionExpiresAt?: string;\n};\n\nexport type AuthErrorCode =\n | 'USER_NOT_FOUND'\n | 'INVALID_PASSWORD'\n | 'USER_EXISTS'\n | 'VERIFICATION_EXPIRED'\n | 'VERIFICATION_MISMATCH'\n | 'VERIFICATION_NOT_FOUND'\n | 'TOO_MANY_ATTEMPTS'\n | 'REQUIRES_VERIFICATION'\n | 'UNAUTHORIZED'\n | 'ACCESS_DENIED'\n | 'HAS_NO_PASSWORD'\n | 'PASSWORD_ALREADY_SET';\n\nexport type AuthError = {\n message: string;\n code?: AuthErrorCode;\n status?: number;\n details?: Record<string, unknown>;\n};\n","import type { AuthClientConfig } from '../types';\n\nexport const createCustomFetch = (_config: AuthClientConfig) => {\n return (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n if (input instanceof Request) {\n return fetch(input, { ...init, credentials: 'include' });\n }\n return fetch(input, { ...init, credentials: 'include' });\n };\n};\n"],"mappings":"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","names":["error"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/cookie.ts","../src/provider.tsx","../src/lib/translations.ts","../src/types.ts","../src/utils/custom-fetch.ts"],"sourcesContent":["import type { AuthClientConfig } from '../types';\n\nconst isProduction =\n typeof process !== 'undefined' && process.env.NODE_ENV === 'production';\n\nexport const getSessionCookieName = (config: AuthClientConfig): string => {\n const prefix = config.cookiePrefix || '';\n const baseName = 'session_token';\n if (prefix) {\n return `${prefix}_${baseName}`;\n }\n return isProduction ? '__Host-session_token' : baseName;\n};\n","'use client';\n\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { deepmerge } from 'deepmerge-ts';\nimport createFetchClient from 'openapi-fetch';\nimport createClient from 'openapi-react-query';\nimport type { ReactNode } from 'react';\nimport { createContext, useContext, useMemo, useState } from 'react';\nimport type { paths } from './data/openapi';\nimport { createTranslator } from './lib/translations';\nimport {\n type AuthClientConfig,\n type AuthResponse,\n defaultAuthClientConfig,\n type Session,\n type User,\n} from './types';\nimport { getSessionCookieName } from './utils/cookie';\nimport { createCustomFetch } from './utils/custom-fetch';\n\n// biome-ignore lint/suspicious/noExplicitAny: OpenAPI hooks type\ntype OpenApiHooks = any;\n\n// --- Utility: Check if running on server ---\nfunction isServer(): boolean {\n return typeof document === 'undefined';\n}\n\n/**\n * @deprecated Cookie is httpOnly and cannot be read client-side.\n * Use `useSession().isAuthenticated` instead.\n * This function always returns false on client.\n */\nexport function hasAuthCookie(_cookieName: string): boolean {\n // Cookie is httpOnly, can't check client-side\n // Always return false - use useSession() for auth status\n return false;\n}\n\n// --- Types ---\nexport type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated';\n\ntype AuthState = {\n user: User | null;\n session: Session | null;\n status: AuthStatus;\n error: Error | null;\n};\n\ntype SessionContextValue = AuthState & {\n isLoading: boolean;\n isAuthenticated: boolean;\n refresh: () => Promise<void>;\n signOut: () => Promise<void>;\n};\n\ntype ApiContextValue = {\n hooks: OpenApiHooks;\n setAuth: (auth: AuthResponse) => void;\n clearAuth: () => void;\n refresh: () => Promise<void>;\n};\n\ntype ConfigContextValue = {\n config: AuthClientConfig;\n cookieName: string;\n t: (key: string, params?: Record<string, string | number>) => string;\n};\n\nconst SessionContext = createContext<SessionContextValue | null>(null);\nconst ApiContext = createContext<ApiContextValue | null>(null);\nconst ConfigContext = createContext<ConfigContextValue | null>(null);\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n },\n },\n});\n\n// --- Hooks ---\n\n/**\n * Get session state including user, session, and auth status.\n * - `status`: 'loading' | 'authenticated' | 'unauthenticated'\n * - `isLoading`: true while fetching session\n * - `isAuthenticated`: true if user and session exist\n */\nexport function useSession(): SessionContextValue {\n const context = useContext(SessionContext);\n if (!context) {\n throw new Error('useSession must be used within MesobAuthProvider');\n }\n return context;\n}\n\nexport function useApi(): ApiContextValue {\n const context = useContext(ApiContext);\n if (!context) {\n throw new Error('useApi must be used within MesobAuthProvider');\n }\n return context;\n}\n\nexport function useConfig(): ConfigContextValue {\n const context = useContext(ConfigContext);\n if (!context) {\n throw new Error('useConfig must be used within MesobAuthProvider');\n }\n return context;\n}\n\n/**\n * @deprecated Cookie is httpOnly, can't be checked client-side.\n * Use `useSession().isAuthenticated` instead.\n */\nexport function useHasAuthCookie(): boolean {\n const { status } = useSession();\n return status === 'authenticated' || status === 'loading';\n}\n\n// --- Provider ---\n\ntype MesobAuthProviderProps = {\n config: AuthClientConfig;\n children: ReactNode;\n};\n\nexport function MesobAuthProvider({\n config,\n children,\n}: MesobAuthProviderProps) {\n const mergedConfig = useMemo(\n () =>\n deepmerge(\n { ...defaultAuthClientConfig } as Partial<AuthClientConfig>,\n config,\n ) as AuthClientConfig,\n [config],\n );\n\n const api = useMemo(\n () =>\n createFetchClient<paths>({\n baseUrl: mergedConfig.baseURL,\n fetch: createCustomFetch(mergedConfig),\n }),\n [mergedConfig],\n );\n\n const hooks = useMemo(() => createClient(api), [api]);\n const cookieName = useMemo(\n () => getSessionCookieName(mergedConfig),\n [mergedConfig],\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <AuthStateProvider\n config={mergedConfig}\n hooks={hooks}\n cookieName={cookieName}\n >\n {children}\n </AuthStateProvider>\n </QueryClientProvider>\n );\n}\n\ntype AuthStateProviderProps = {\n config: AuthClientConfig;\n hooks: OpenApiHooks;\n cookieName: string;\n children: ReactNode;\n};\n\nfunction AuthStateProvider({\n config,\n hooks,\n cookieName,\n children,\n}: AuthStateProviderProps) {\n // Manual override for sign-out / sign-in\n const [override, setOverride] = useState<AuthState | null>(null);\n\n // Always fetch session - cookie is httpOnly, can't check client-side\n // Server will read the cookie and return user/session if valid\n const {\n data: sessionData,\n isLoading,\n isFetched,\n error: sessionError,\n refetch,\n } = hooks.useQuery(\n 'get',\n '/session',\n {},\n {\n enabled: !(override || isServer()),\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n retry: false,\n gcTime: 0,\n staleTime: 0,\n },\n );\n\n // Derive state directly - no useEffect\n const user = override?.user ?? sessionData?.user ?? null;\n const session = override?.session ?? sessionData?.session ?? null;\n const error = override?.error ?? (sessionError as Error | null);\n\n // Check error status code\n const errorStatus = (() => {\n if (!sessionError) {\n return null;\n }\n const err = sessionError as { status?: number };\n return err.status ?? null;\n })();\n\n // Check if error is a network/connection error\n const isNetworkError = (() => {\n if (!sessionError) {\n return false;\n }\n const error = sessionError as Error & { cause?: unknown; data?: unknown };\n const errorMessage =\n error.message || String(error) || JSON.stringify(error);\n // Network errors: TypeError, DOMException, or fetch failures\n if (\n error instanceof TypeError ||\n error instanceof DOMException ||\n error.name === 'TypeError' ||\n errorMessage.includes('Failed to fetch') ||\n errorMessage.includes('ERR_CONNECTION_REFUSED') ||\n errorMessage.includes('NetworkError') ||\n errorMessage.includes('Network request failed') ||\n errorMessage.includes('fetch failed')\n ) {\n return true;\n }\n // Check error cause\n if (error.cause) {\n const causeStr = String(error.cause);\n if (\n causeStr.includes('Failed to fetch') ||\n causeStr.includes('ERR_CONNECTION_REFUSED') ||\n causeStr.includes('NetworkError')\n ) {\n return true;\n }\n }\n return false;\n })();\n\n // Compute status\n // biome-ignore lint: Status determination requires multiple checks\n const status: AuthStatus = (() => {\n if (override) {\n return override.status;\n }\n if (isServer()) {\n return 'loading';\n }\n if (user && session) {\n return 'authenticated';\n }\n // Check for network errors or auth errors first - allow auth page to show\n if (isNetworkError || errorStatus === 401) {\n return 'unauthenticated';\n }\n // If we have an error but it's not a network error, still check loading state\n if (sessionError && !isNetworkError && errorStatus !== 401) {\n if (errorStatus && errorStatus >= 500) {\n return 'authenticated';\n }\n // Other errors mean unauthenticated\n if (isFetched) {\n return 'unauthenticated';\n }\n }\n if (isLoading || !isFetched) {\n return 'loading';\n }\n if (isFetched && !user && !session) {\n return 'unauthenticated';\n }\n return 'unauthenticated';\n })();\n\n const signOutMutation = hooks.useMutation('post', '/sign-out');\n const t = createTranslator(config.messages || {});\n\n const setAuth = (auth: AuthResponse) => {\n setOverride({\n user: auth.user,\n session: auth.session,\n status: 'authenticated',\n error: null,\n });\n };\n\n const clearAuth = () => {\n setOverride({\n user: null,\n session: null,\n status: 'unauthenticated',\n error: null,\n });\n };\n\n const refresh = async () => {\n setOverride(null);\n await refetch();\n };\n\n const signOut = async () => {\n await signOutMutation.mutateAsync({});\n clearAuth();\n\n const redirectUrl = config.navigation?.defaultRedirectUrl || '/';\n\n if (config.navigation?.onNavigate) {\n config.navigation.onNavigate(redirectUrl);\n } else if (typeof window !== 'undefined') {\n window.location.href = redirectUrl;\n }\n };\n\n return (\n <ConfigContext.Provider value={{ config, cookieName, t }}>\n <ApiContext.Provider value={{ hooks, setAuth, clearAuth, refresh }}>\n <SessionContext.Provider\n value={{\n user,\n session,\n status,\n error,\n isLoading: status === 'loading',\n isAuthenticated: status === 'authenticated',\n refresh,\n signOut,\n }}\n >\n {children}\n </SessionContext.Provider>\n </ApiContext.Provider>\n </ConfigContext.Provider>\n );\n}\n","type Messages = Record<string, unknown>;\n\nexport function createTranslator(messages: Messages, namespace?: string) {\n return (key: string, params?: Record<string, string | number>): string => {\n const fullKey = namespace ? `${namespace}.${key}` : key;\n const keys = fullKey.split('.');\n\n let value: unknown = messages;\n for (const k of keys) {\n if (value && typeof value === 'object' && value !== null) {\n value = (value as Record<string, unknown>)[k];\n } else {\n return fullKey;\n }\n }\n\n if (typeof value !== 'string') {\n return fullKey;\n }\n\n // Simple parameter replacement\n if (params) {\n return value.replace(/\\{(\\w+)\\}/g, (_, param) =>\n String(params[param] ?? `{${param}}`),\n );\n }\n\n return value;\n };\n}\n","import type { PermissionTree } from '@mesob/common';\n\nexport type UIConfig = {\n logo: React.ReactNode;\n name: React.ReactNode;\n logoImage?: string;\n};\n\nexport type FeaturesConfig = {\n enableSignup?: boolean;\n enablePasswordReset?: boolean;\n enableEmailSignup?: boolean;\n enablePhoneSignup?: boolean;\n enableEmailSignIn?: boolean;\n enablePhoneSignIn?: boolean;\n allowedSignupEmailDomains?: string[];\n enableSocialSignup?: boolean;\n socialProviders?: string[];\n};\n\nexport type TenantConfig = {\n enabled: boolean;\n tenantId: string;\n};\n\nexport type NavigationConfig = {\n locale?: string;\n defaultRedirectUrl?: string;\n onNavigate?: (path: string) => void;\n linkComponent?: React.ComponentType<\n React.ComponentProps<'a'> & { href: string }\n >;\n links?: {\n signIn?: string;\n signUp?: string;\n forgotPassword?: string;\n setPassword?: string;\n };\n};\n\nexport type AuthClientConfig = {\n baseURL: string;\n ui: UIConfig;\n features?: FeaturesConfig;\n tenant?: TenantConfig;\n permissions?: PermissionTree;\n navigation?: NavigationConfig;\n messages?: Record<string, unknown>;\n cookiePrefix?: string;\n phoneRegex?: RegExp | string;\n /** Default userType filter for users list (e.g. 'employee'). Omit or 'all' to show all. */\n defaultUserType?: string;\n};\n\ntype DefaultAuthClientConfig = {\n readonly features: {\n readonly enableSignup: true;\n readonly enablePasswordReset: true;\n readonly enableEmailSignup: true;\n readonly enablePhoneSignup: true;\n readonly enableEmailSignIn: true;\n readonly enablePhoneSignIn: true;\n readonly allowedSignupEmailDomains: [];\n readonly enableSocialSignup: false;\n readonly socialProviders: [];\n };\n readonly navigation: {\n readonly locale: 'en';\n };\n readonly cookiePrefix: 'msb';\n readonly phoneRegex: RegExp;\n};\n\nexport const defaultAuthClientConfig: DefaultAuthClientConfig = {\n features: {\n enableSignup: true,\n enablePasswordReset: true,\n enableEmailSignup: true,\n enablePhoneSignup: true,\n enableEmailSignIn: true,\n enablePhoneSignIn: true,\n allowedSignupEmailDomains: [],\n enableSocialSignup: false,\n socialProviders: [],\n },\n navigation: {\n locale: 'en',\n },\n cookiePrefix: 'msb',\n phoneRegex: /^(\\+2519|\\+2517|2519|2517|09|07)\\d{8}$/,\n} as const;\n\nexport type User = {\n id: string;\n tenantId: string;\n fullName: string;\n email: string | null;\n phone: string | null;\n handle?: string;\n image: string | null;\n emailVerified: boolean;\n phoneVerified: boolean;\n lastSignInAt?: string | null;\n /** Role IDs */\n roles?: string[] | null;\n roleCodes?: string[] | null;\n permissions?: string[] | null;\n};\n\nexport type Session = {\n id?: string;\n expiresAt: string;\n createdAt?: string;\n userAgent?: string | null;\n ip?: string | null;\n};\n\nexport type AuthResponse = {\n user: User;\n session: Session;\n sessionToken?: string;\n sessionExpiresAt?: string;\n};\n\nexport type AuthErrorCode =\n | 'USER_NOT_FOUND'\n | 'INVALID_PASSWORD'\n | 'USER_EXISTS'\n | 'VERIFICATION_EXPIRED'\n | 'VERIFICATION_MISMATCH'\n | 'VERIFICATION_NOT_FOUND'\n | 'TOO_MANY_ATTEMPTS'\n | 'REQUIRES_VERIFICATION'\n | 'UNAUTHORIZED'\n | 'ACCESS_DENIED'\n | 'HAS_NO_PASSWORD'\n | 'PASSWORD_ALREADY_SET';\n\nexport type AuthError = {\n message: string;\n code?: AuthErrorCode;\n status?: number;\n details?: Record<string, unknown>;\n};\n","import type { AuthClientConfig } from '../types';\n\nexport const createCustomFetch = (_config: AuthClientConfig) => {\n return (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n if (input instanceof Request) {\n return fetch(input, { ...init, credentials: 'include' });\n }\n return fetch(input, { ...init, credentials: 'include' });\n };\n};\n"],"mappings":"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","names":["error"]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
useApi,
|
|
6
6
|
useConfig,
|
|
7
7
|
useSession
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2XIZ27DU.js";
|
|
9
9
|
|
|
10
10
|
// src/components/profile/request-change-phone-form.tsx
|
|
11
11
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
@@ -269,4 +269,4 @@ function RequestChangePhoneForm({
|
|
|
269
269
|
export {
|
|
270
270
|
RequestChangePhoneForm
|
|
271
271
|
};
|
|
272
|
-
//# sourceMappingURL=chunk-
|
|
272
|
+
//# sourceMappingURL=chunk-4CUQIZ2Q.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VerifyChangeEmailForm
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KWL6FBP7.js";
|
|
4
4
|
import {
|
|
5
5
|
RequestChangeEmailForm
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WTAKMSWN.js";
|
|
7
7
|
import {
|
|
8
8
|
useSession
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2XIZ27DU.js";
|
|
10
10
|
|
|
11
11
|
// src/components/profile/change-email-form.tsx
|
|
12
12
|
import {
|
|
@@ -91,4 +91,4 @@ function ChangeEmailForm() {
|
|
|
91
91
|
export {
|
|
92
92
|
ChangeEmailForm
|
|
93
93
|
};
|
|
94
|
-
//# sourceMappingURL=chunk-
|
|
94
|
+
//# sourceMappingURL=chunk-55WFD2Y2.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useApi
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2XIZ27DU.js";
|
|
4
4
|
|
|
5
5
|
// src/components/iam/permission-selector.tsx
|
|
6
6
|
import {
|
|
@@ -90,4 +90,4 @@ function PermissionSelector({
|
|
|
90
90
|
export {
|
|
91
91
|
PermissionSelector
|
|
92
92
|
};
|
|
93
|
-
//# sourceMappingURL=chunk-
|
|
93
|
+
//# sourceMappingURL=chunk-6L4K26KM.js.map
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
authApi$
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QJOBPOTR.js";
|
|
4
4
|
import {
|
|
5
5
|
defaultEntityQueryOptions
|
|
6
6
|
} from "./chunk-NPW7D2HZ.js";
|
|
7
7
|
import {
|
|
8
8
|
IAMGuard
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DJWX4ENN.js";
|
|
10
10
|
import {
|
|
11
11
|
useApi,
|
|
12
12
|
useConfig
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2XIZ27DU.js";
|
|
14
14
|
|
|
15
15
|
// src/components/iam/domains-page.tsx
|
|
16
16
|
import {
|
|
@@ -598,4 +598,4 @@ function DomainsPageContent() {
|
|
|
598
598
|
export {
|
|
599
599
|
DomainsPage
|
|
600
600
|
};
|
|
601
|
-
//# sourceMappingURL=chunk-
|
|
601
|
+
//# sourceMappingURL=chunk-BIP5XEDV.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-TFVBER3Y.js";
|
|
4
4
|
import {
|
|
5
5
|
useApi
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2XIZ27DU.js";
|
|
7
7
|
|
|
8
8
|
// src/components/iam/sessions.tsx
|
|
9
9
|
import { Button } from "@mesob/ui/components";
|
|
@@ -95,4 +95,4 @@ function Sessions() {
|
|
|
95
95
|
export {
|
|
96
96
|
Sessions
|
|
97
97
|
};
|
|
98
|
-
//# sourceMappingURL=chunk-
|
|
98
|
+
//# sourceMappingURL=chunk-C34HWZA5.js.map
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
} from "./chunk-NPW7D2HZ.js";
|
|
4
4
|
import {
|
|
5
5
|
IAMGuard
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DJWX4ENN.js";
|
|
7
7
|
import {
|
|
8
8
|
useApi,
|
|
9
9
|
useConfig
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-2XIZ27DU.js";
|
|
11
11
|
|
|
12
12
|
// src/components/iam/permissions-page.tsx
|
|
13
13
|
import {
|
|
@@ -278,4 +278,4 @@ function PermissionsPageContent() {
|
|
|
278
278
|
export {
|
|
279
279
|
PermissionsPage
|
|
280
280
|
};
|
|
281
|
-
//# sourceMappingURL=chunk-
|
|
281
|
+
//# sourceMappingURL=chunk-CDX5V66G.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Grant
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PCBJBXEK.js";
|
|
4
4
|
|
|
5
5
|
// src/components/iam/iam-guard.tsx
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -12,4 +12,4 @@ function IAMGuard({ fallback = null, children }) {
|
|
|
12
12
|
export {
|
|
13
13
|
IAMGuard
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=chunk-
|
|
15
|
+
//# sourceMappingURL=chunk-DJWX4ENN.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// src/utils/safe-redirect.ts
|
|
2
|
+
function getSafeRedirectFromSearch(search) {
|
|
3
|
+
try {
|
|
4
|
+
const raw = new URLSearchParams(
|
|
5
|
+
search.startsWith("?") ? search.slice(1) : search
|
|
6
|
+
).get("redirect");
|
|
7
|
+
if (!raw) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const decoded = decodeURIComponent(raw);
|
|
11
|
+
if (decoded.startsWith("/") && !decoded.startsWith("//")) {
|
|
12
|
+
return decoded;
|
|
13
|
+
}
|
|
14
|
+
} catch {
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export {
|
|
20
|
+
getSafeRedirectFromSearch
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=chunk-G2XRGSQE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/safe-redirect.ts"],"sourcesContent":["/** Same-origin path only; blocks //evil open redirects */\nexport function getSafeRedirectFromSearch(search: string): string | null {\n try {\n const raw = new URLSearchParams(\n search.startsWith('?') ? search.slice(1) : search,\n ).get('redirect');\n if (!raw) {\n return null;\n }\n const decoded = decodeURIComponent(raw);\n if (decoded.startsWith('/') && !decoded.startsWith('//')) {\n return decoded;\n }\n } catch {\n // malformed query\n }\n return null;\n}\n"],"mappings":";AACO,SAAS,0BAA0B,QAA+B;AACvE,MAAI;AACF,UAAM,MAAM,IAAI;AAAA,MACd,OAAO,WAAW,GAAG,IAAI,OAAO,MAAM,CAAC,IAAI;AAAA,IAC7C,EAAE,IAAI,UAAU;AAChB,QAAI,CAAC,KAAK;AACR,aAAO;AAAA,IACT;AACA,UAAM,UAAU,mBAAmB,GAAG;AACtC,QAAI,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,WAAW,IAAI,GAAG;AACxD,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;","names":[]}
|
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
Link,
|
|
6
6
|
authApi$
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QJOBPOTR.js";
|
|
8
8
|
import {
|
|
9
9
|
defaultEntityQueryOptions
|
|
10
10
|
} from "./chunk-NPW7D2HZ.js";
|
|
11
11
|
import {
|
|
12
12
|
IAMGuard
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-DJWX4ENN.js";
|
|
14
14
|
import {
|
|
15
15
|
useApi,
|
|
16
16
|
useConfig
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-2XIZ27DU.js";
|
|
18
18
|
|
|
19
19
|
// src/components/iam/tenants-page.tsx
|
|
20
20
|
import {
|
|
@@ -541,4 +541,4 @@ function TenantsPageContent() {
|
|
|
541
541
|
export {
|
|
542
542
|
TenantsPage
|
|
543
543
|
};
|
|
544
|
-
//# sourceMappingURL=chunk-
|
|
544
|
+
//# sourceMappingURL=chunk-GXWBGB6G.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
OtpVerificationModal
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XGE6G3EK.js";
|
|
4
4
|
import {
|
|
5
5
|
useApi,
|
|
6
6
|
useSession
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2XIZ27DU.js";
|
|
8
8
|
|
|
9
9
|
// src/components/profile/verify-change-phone-form.tsx
|
|
10
10
|
import { useState } from "react";
|
|
@@ -140,4 +140,4 @@ function VerifyChangePhoneForm({
|
|
|
140
140
|
export {
|
|
141
141
|
VerifyChangePhoneForm
|
|
142
142
|
};
|
|
143
|
-
//# sourceMappingURL=chunk-
|
|
143
|
+
//# sourceMappingURL=chunk-HVAYVDIM.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-TFVBER3Y.js";
|
|
4
4
|
import {
|
|
5
5
|
useApi
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2XIZ27DU.js";
|
|
7
7
|
|
|
8
8
|
// src/components/iam/users.tsx
|
|
9
9
|
import { Badge, Button } from "@mesob/ui/components";
|
|
@@ -104,4 +104,4 @@ function Users() {
|
|
|
104
104
|
export {
|
|
105
105
|
Users
|
|
106
106
|
};
|
|
107
|
-
//# sourceMappingURL=chunk-
|
|
107
|
+
//# sourceMappingURL=chunk-J4Q7RYYY.js.map
|
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
} from "./chunk-DPH2PHK3.js";
|
|
7
7
|
import {
|
|
8
8
|
useTranslator
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XUV6CYTY.js";
|
|
10
10
|
import {
|
|
11
11
|
useApi,
|
|
12
12
|
useConfig
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2XIZ27DU.js";
|
|
14
14
|
|
|
15
15
|
// src/components/auth/sign-up.tsx
|
|
16
16
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
@@ -36,6 +36,8 @@ import { toast } from "sonner";
|
|
|
36
36
|
import { z } from "zod";
|
|
37
37
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
38
38
|
var isPhone = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
|
|
39
|
+
var isEmail = (s) => z.email().safeParse(s).success;
|
|
40
|
+
var normalizeDomain = (value) => value.trim().toLowerCase().replace(/^@/, "");
|
|
39
41
|
function PasswordInput({
|
|
40
42
|
field,
|
|
41
43
|
show,
|
|
@@ -69,19 +71,41 @@ function PasswordInput({
|
|
|
69
71
|
)
|
|
70
72
|
] });
|
|
71
73
|
}
|
|
72
|
-
var signUpSchema = (t) => z.object({
|
|
74
|
+
var signUpSchema = (t, options) => z.object({
|
|
73
75
|
fullName: z.string().min(1, t("errors.fullNameRequired")),
|
|
74
|
-
identifier: z.string().min(1, t("errors.contactRequired")).
|
|
75
|
-
(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
identifier: z.string().trim().min(1, t("errors.contactRequired")).superRefine((value, ctx) => {
|
|
77
|
+
const emailInput = isEmail(value);
|
|
78
|
+
const phoneInput = isPhone(value);
|
|
79
|
+
if (!(emailInput || phoneInput)) {
|
|
80
|
+
ctx.addIssue({
|
|
81
|
+
code: z.ZodIssueCode.custom,
|
|
82
|
+
message: t("errors.invalidEmailOrPhone")
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (emailInput && !options.allowEmailSignup) {
|
|
87
|
+
ctx.addIssue({
|
|
88
|
+
code: z.ZodIssueCode.custom,
|
|
89
|
+
message: "Email sign up is disabled"
|
|
90
|
+
});
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (phoneInput && !options.allowPhoneSignup) {
|
|
94
|
+
ctx.addIssue({
|
|
95
|
+
code: z.ZodIssueCode.custom,
|
|
96
|
+
message: "Phone sign up is disabled"
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (emailInput && options.allowedSignupEmailDomains.length > 0 && !options.allowedSignupEmailDomains.includes(
|
|
101
|
+
normalizeDomain(value.split("@")[1] || "")
|
|
102
|
+
)) {
|
|
103
|
+
ctx.addIssue({
|
|
104
|
+
code: z.ZodIssueCode.custom,
|
|
105
|
+
message: "Email domain is not allowed for sign up"
|
|
106
|
+
});
|
|
83
107
|
}
|
|
84
|
-
),
|
|
108
|
+
}),
|
|
85
109
|
password: z.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError")),
|
|
86
110
|
confirmPassword: z.string()
|
|
87
111
|
}).refine((data) => data.password === data.confirmPassword, {
|
|
@@ -101,6 +125,12 @@ var SignUp = ({
|
|
|
101
125
|
const [error, setError] = useState(null);
|
|
102
126
|
const [showPassword, setShowPassword] = useState(false);
|
|
103
127
|
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
|
|
128
|
+
const signupEnabled = config.features?.enableSignup !== false;
|
|
129
|
+
const allowEmailSignup = config.features?.enableEmailSignup !== false;
|
|
130
|
+
const allowPhoneSignup = config.features?.enablePhoneSignup !== false;
|
|
131
|
+
const allowedSignupEmailDomains = (config.features?.allowedSignupEmailDomains || []).map(normalizeDomain).filter(Boolean);
|
|
132
|
+
const hasSignupIdentifierChannel = allowEmailSignup || allowPhoneSignup;
|
|
133
|
+
const isSignupAvailable = signupEnabled && hasSignupIdentifierChannel;
|
|
104
134
|
const signUpMutation = hooks.useMutation("post", "/sign-up");
|
|
105
135
|
const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
|
|
106
136
|
const onNavigate = config.navigation?.onNavigate || ((path) => {
|
|
@@ -112,7 +142,13 @@ var SignUp = ({
|
|
|
112
142
|
const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
|
|
113
143
|
const hasInitialIdentifier = !!initialIdentifier;
|
|
114
144
|
const form = useForm({
|
|
115
|
-
resolver: zodResolver(
|
|
145
|
+
resolver: zodResolver(
|
|
146
|
+
signUpSchema(t, {
|
|
147
|
+
allowEmailSignup,
|
|
148
|
+
allowPhoneSignup,
|
|
149
|
+
allowedSignupEmailDomains
|
|
150
|
+
})
|
|
151
|
+
),
|
|
116
152
|
defaultValues: {
|
|
117
153
|
fullName: "",
|
|
118
154
|
identifier: initialIdentifier || "",
|
|
@@ -135,11 +171,21 @@ var SignUp = ({
|
|
|
135
171
|
}
|
|
136
172
|
}, [error]);
|
|
137
173
|
const handleSubmit = form.handleSubmit(async (values) => {
|
|
174
|
+
if (!signupEnabled) {
|
|
175
|
+
form.setError("identifier", { message: "Sign up is disabled" });
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (!hasSignupIdentifierChannel) {
|
|
179
|
+
form.setError("identifier", {
|
|
180
|
+
message: "Sign up is unavailable for email and phone"
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
138
184
|
setIsLoading(true);
|
|
139
185
|
setError(null);
|
|
140
186
|
try {
|
|
141
|
-
const identifier = values.identifier;
|
|
142
|
-
const usingPhone = isPhone(identifier);
|
|
187
|
+
const identifier = values.identifier.trim();
|
|
188
|
+
const usingPhone = allowPhoneSignup && (isPhone(identifier) || !allowEmailSignup);
|
|
143
189
|
const res = await signUpMutation.mutateAsync({
|
|
144
190
|
body: usingPhone ? {
|
|
145
191
|
phone: identifier,
|
|
@@ -175,6 +221,12 @@ var SignUp = ({
|
|
|
175
221
|
}
|
|
176
222
|
});
|
|
177
223
|
const getIdentifierLabel = () => {
|
|
224
|
+
if (allowEmailSignup && !allowPhoneSignup) {
|
|
225
|
+
return t("form.emailLabel");
|
|
226
|
+
}
|
|
227
|
+
if (!allowEmailSignup && allowPhoneSignup) {
|
|
228
|
+
return t("form.phoneLabel");
|
|
229
|
+
}
|
|
178
230
|
if (!hasInitialIdentifier) {
|
|
179
231
|
return t("form.accountLabel") || "Email/Phone";
|
|
180
232
|
}
|
|
@@ -184,6 +236,16 @@ var SignUp = ({
|
|
|
184
236
|
return t("form.phoneLabel");
|
|
185
237
|
};
|
|
186
238
|
const identifierLabel = getIdentifierLabel();
|
|
239
|
+
let signupUnavailableDescription = "No sign up channel is enabled.";
|
|
240
|
+
if (!signupEnabled) {
|
|
241
|
+
signupUnavailableDescription = "Sign up is disabled.";
|
|
242
|
+
}
|
|
243
|
+
let identifierInputType = "email";
|
|
244
|
+
if (!allowEmailSignup && allowPhoneSignup) {
|
|
245
|
+
identifierInputType = "tel";
|
|
246
|
+
} else if (allowEmailSignup && allowPhoneSignup) {
|
|
247
|
+
identifierInputType = isPhone(form.watch("identifier")) ? "tel" : "email";
|
|
248
|
+
}
|
|
187
249
|
let errorContent = null;
|
|
188
250
|
if (error) {
|
|
189
251
|
if (typeof error === "string") {
|
|
@@ -215,6 +277,11 @@ var SignUp = ({
|
|
|
215
277
|
)
|
|
216
278
|
] }),
|
|
217
279
|
children: [
|
|
280
|
+
isSignupAvailable ? null : /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
|
|
281
|
+
/* @__PURE__ */ jsx(IconAlertCircle, { className: "h-4 w-4" }),
|
|
282
|
+
/* @__PURE__ */ jsx(AlertTitle, { children: "Sign up unavailable" }),
|
|
283
|
+
/* @__PURE__ */ jsx(AlertDescription, { children: signupUnavailableDescription })
|
|
284
|
+
] }),
|
|
218
285
|
/* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs(
|
|
219
286
|
"form",
|
|
220
287
|
{
|
|
@@ -252,8 +319,8 @@ var SignUp = ({
|
|
|
252
319
|
Input,
|
|
253
320
|
{
|
|
254
321
|
...field,
|
|
255
|
-
type:
|
|
256
|
-
autoComplete:
|
|
322
|
+
type: identifierInputType,
|
|
323
|
+
autoComplete: identifierInputType,
|
|
257
324
|
disabled: hasInitialIdentifier
|
|
258
325
|
}
|
|
259
326
|
) }),
|
|
@@ -307,7 +374,7 @@ var SignUp = ({
|
|
|
307
374
|
type: "submit",
|
|
308
375
|
form: "sign-up-form",
|
|
309
376
|
className: "w-full",
|
|
310
|
-
disabled: isLoading || signUpMutation.isPending,
|
|
377
|
+
disabled: isLoading || signUpMutation.isPending || !signupEnabled || !hasSignupIdentifierChannel,
|
|
311
378
|
children: isLoading || signUpMutation.isPending ? t("form.submitting") : t("form.submit")
|
|
312
379
|
}
|
|
313
380
|
)
|
|
@@ -327,4 +394,4 @@ var SignUp = ({
|
|
|
327
394
|
export {
|
|
328
395
|
SignUp
|
|
329
396
|
};
|
|
330
|
-
//# sourceMappingURL=chunk-
|
|
397
|
+
//# sourceMappingURL=chunk-JNVJWNJT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/auth/sign-up.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n Button,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n useFormField,\n} from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle, IconEye, IconEyeOff } from '@tabler/icons-react';\nimport type { ChangeEvent, ComponentProps } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { handleError } from '../../utils/handle-error';\nimport { AuthLayout } from './auth-layout';\n\nconst isPhone = (s: string) => /^\\+?[0-9()[\\]\\s-]{6,}$/.test(s);\nconst isEmail = (s: string) => z.email().safeParse(s).success;\nconst normalizeDomain = (value: string) =>\n value.trim().toLowerCase().replace(/^@/, '');\n\ntype SignUpValidationOptions = {\n allowEmailSignup: boolean;\n allowPhoneSignup: boolean;\n allowedSignupEmailDomains: string[];\n};\n\ntype PasswordInputProps = {\n field: ComponentProps<'input'> & {\n value: string;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n onBlur: () => void;\n };\n show: boolean;\n onToggle: () => void;\n autoComplete?: 'current-password' | 'new-password';\n};\n\nfunction PasswordInput({\n field,\n show,\n onToggle,\n autoComplete = 'current-password',\n}: PasswordInputProps) {\n const { formItemId, error } = useFormField();\n return (\n <div className=\"relative\">\n <Input\n {...field}\n id={formItemId}\n type={show ? 'text' : 'password'}\n autoComplete={autoComplete}\n aria-invalid={!!error}\n className=\"pr-10\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-0 top-0 h-full px-3 text-muted-foreground hover:text-foreground\"\n onClick={onToggle}\n aria-label={show ? 'Hide password' : 'Show password'}\n >\n {show ? (\n <IconEyeOff className=\"h-4 w-4\" />\n ) : (\n <IconEye className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n );\n}\n\ntype SignUpFormValues = {\n fullName: string;\n identifier: string;\n password: string;\n confirmPassword: string;\n};\n\ntype SignUpProps = {\n redirectUrl?: string;\n initialIdentifier?: string;\n};\n\nconst signUpSchema = (\n t: (key: string) => string,\n options: SignUpValidationOptions,\n) =>\n z\n .object({\n fullName: z.string().min(1, t('errors.fullNameRequired')),\n identifier: z\n .string()\n .trim()\n .min(1, t('errors.contactRequired'))\n .superRefine((value, ctx) => {\n const emailInput = isEmail(value);\n const phoneInput = isPhone(value);\n if (!(emailInput || phoneInput)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: t('errors.invalidEmailOrPhone'),\n });\n return;\n }\n if (emailInput && !options.allowEmailSignup) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Email sign up is disabled',\n });\n return;\n }\n if (phoneInput && !options.allowPhoneSignup) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Phone sign up is disabled',\n });\n return;\n }\n if (\n emailInput &&\n options.allowedSignupEmailDomains.length > 0 &&\n !options.allowedSignupEmailDomains.includes(\n normalizeDomain(value.split('@')[1] || ''),\n )\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Email domain is not allowed for sign up',\n });\n }\n }),\n password: z\n .string()\n .min(8, t('errors.passwordLength'))\n .max(128, t('errors.longPasswordError')),\n confirmPassword: z.string(),\n })\n .refine((data) => data.password === data.confirmPassword, {\n message: t('errors.passwordsMismatch'),\n path: ['confirmPassword'],\n });\n\nexport const SignUp = ({\n redirectUrl,\n initialIdentifier,\n}: SignUpProps = {}) => {\n const { hooks, setAuth } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const t = useTranslator('Auth.signUp');\n const Link = mesob?.navigation?.Link;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmPassword, setShowConfirmPassword] = useState(false);\n const signupEnabled = config.features?.enableSignup !== false;\n const allowEmailSignup = config.features?.enableEmailSignup !== false;\n const allowPhoneSignup = config.features?.enablePhoneSignup !== false;\n const allowedSignupEmailDomains = (\n config.features?.allowedSignupEmailDomains || []\n )\n .map(normalizeDomain)\n .filter(Boolean);\n const hasSignupIdentifierChannel = allowEmailSignup || allowPhoneSignup;\n const isSignupAvailable = signupEnabled && hasSignupIdentifierChannel;\n\n const signUpMutation = hooks.useMutation('post', '/sign-up');\n\n const signInLink = config.navigation?.links?.signIn || '/auth/sign-in';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n const defaultRedirect =\n redirectUrl || config.navigation?.defaultRedirectUrl || '/';\n\n const hasInitialIdentifier = !!initialIdentifier;\n\n const form = useForm<SignUpFormValues>({\n resolver: zodResolver(\n signUpSchema(t, {\n allowEmailSignup,\n allowPhoneSignup,\n allowedSignupEmailDomains,\n }),\n ),\n defaultValues: {\n fullName: '',\n identifier: initialIdentifier || '',\n password: '',\n confirmPassword: '',\n },\n mode: 'onSubmit',\n reValidateMode: 'onSubmit',\n });\n\n useEffect(() => {\n if (initialIdentifier) {\n form.setValue('identifier', initialIdentifier);\n }\n }, [initialIdentifier, form]);\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n const handleSubmit = form.handleSubmit(async (values) => {\n if (!signupEnabled) {\n form.setError('identifier', { message: 'Sign up is disabled' });\n return;\n }\n if (!hasSignupIdentifierChannel) {\n form.setError('identifier', {\n message: 'Sign up is unavailable for email and phone',\n });\n return;\n }\n setIsLoading(true);\n setError(null);\n\n try {\n const identifier = values.identifier.trim();\n const usingPhone =\n allowPhoneSignup && (isPhone(identifier) || !allowEmailSignup);\n\n const res = await signUpMutation.mutateAsync({\n body: usingPhone\n ? {\n phone: identifier,\n password: values.password,\n fullName: values.fullName,\n }\n : {\n email: identifier,\n password: values.password,\n fullName: values.fullName,\n },\n });\n\n if ('verificationId' in res && res.verificationId) {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n if (usingPhone) {\n onNavigate(\n `/auth/verify-phone?context=sign-up&verificationId=${res.verificationId}&phone=${encodeURIComponent(identifier)}${redirectParam}`,\n );\n } else {\n onNavigate(\n `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(identifier)}${redirectParam}`,\n );\n }\n return;\n }\n\n if ('user' in res && 'session' in res) {\n setAuth(res);\n }\n onNavigate(defaultRedirect);\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n });\n\n const getIdentifierLabel = () => {\n if (allowEmailSignup && !allowPhoneSignup) {\n return t('form.emailLabel');\n }\n if (!allowEmailSignup && allowPhoneSignup) {\n return t('form.phoneLabel');\n }\n if (!hasInitialIdentifier) {\n return t('form.accountLabel') || 'Email/Phone';\n }\n if (initialIdentifier?.includes('@')) {\n return t('form.emailLabel');\n }\n return t('form.phoneLabel');\n };\n const identifierLabel = getIdentifierLabel();\n let signupUnavailableDescription = 'No sign up channel is enabled.';\n if (!signupEnabled) {\n signupUnavailableDescription = 'Sign up is disabled.';\n }\n\n let identifierInputType: 'email' | 'tel' = 'email';\n if (!allowEmailSignup && allowPhoneSignup) {\n identifierInputType = 'tel';\n } else if (allowEmailSignup && allowPhoneSignup) {\n identifierInputType = isPhone(form.watch('identifier')) ? 'tel' : 'email';\n }\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n return (\n <AuthLayout\n title={config.ui.name}\n description={t('description')}\n logoImage={logoImage}\n footer={\n <p>\n {t('footer.hasAccount')}{' '}\n {Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {t('footer.signInCta')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {t('footer.signInCta')}\n </a>\n )}\n </p>\n }\n >\n {isSignupAvailable ? null : (\n <Alert variant=\"destructive\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>Sign up unavailable</AlertTitle>\n <AlertDescription>{signupUnavailableDescription}</AlertDescription>\n </Alert>\n )}\n <Form {...form}>\n <form\n id=\"sign-up-form\"\n autoComplete=\"on\"\n onSubmit={handleSubmit}\n className=\"space-y-4\"\n >\n <FormField\n control={form.control}\n name=\"fullName\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.fullNameLabel')}</FormLabel>\n <FormControl>\n <Input {...field} autoComplete=\"name\" />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={form.control}\n name=\"identifier\"\n render={({ field }) => (\n <FormItem>\n <FormLabel\n className={hasInitialIdentifier ? 'block' : undefined}\n >\n {identifierLabel}\n </FormLabel>\n <FormControl>\n <Input\n {...field}\n type={identifierInputType}\n autoComplete={identifierInputType}\n disabled={hasInitialIdentifier}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={form.control}\n name=\"password\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.passwordLabel')}</FormLabel>\n <PasswordInput\n field={field}\n show={showPassword}\n onToggle={() => setShowPassword(!showPassword)}\n autoComplete=\"new-password\"\n />\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={form.control}\n name=\"confirmPassword\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.confirmPasswordLabel')}</FormLabel>\n <PasswordInput\n field={field}\n show={showConfirmPassword}\n onToggle={() => setShowConfirmPassword(!showConfirmPassword)}\n autoComplete=\"new-password\"\n />\n <FormMessage />\n </FormItem>\n )}\n />\n <Button\n type=\"submit\"\n form=\"sign-up-form\"\n className=\"w-full\"\n disabled={\n isLoading ||\n signUpMutation.isPending ||\n !signupEnabled ||\n !hasSignupIdentifierChannel\n }\n >\n {isLoading || signUpMutation.isPending\n ? t('form.submitting')\n : t('form.submit')}\n </Button>\n </form>\n </Form>\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n );\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useTranslator
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XUV6CYTY.js";
|
|
4
4
|
|
|
5
5
|
// src/components/auth/countdown.tsx
|
|
6
6
|
import { Spinner } from "@mesob/ui/components";
|
|
@@ -61,4 +61,4 @@ var Countdown = ({
|
|
|
61
61
|
export {
|
|
62
62
|
Countdown
|
|
63
63
|
};
|
|
64
|
-
//# sourceMappingURL=chunk-
|
|
64
|
+
//# sourceMappingURL=chunk-K2523VB5.js.map
|