@mesob/auth-react 0.0.3

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.
Files changed (46) hide show
  1. package/dist/components/auth-card.d.ts +9 -0
  2. package/dist/components/auth-card.js +11 -0
  3. package/dist/components/auth-card.js.map +1 -0
  4. package/dist/components/auth-page-layout.d.ts +14 -0
  5. package/dist/components/auth-page-layout.js +28 -0
  6. package/dist/components/auth-page-layout.js.map +1 -0
  7. package/dist/components/countdown.d.ts +10 -0
  8. package/dist/components/countdown.js +57 -0
  9. package/dist/components/countdown.js.map +1 -0
  10. package/dist/components/forgot-password.d.ts +13 -0
  11. package/dist/components/forgot-password.js +67 -0
  12. package/dist/components/forgot-password.js.map +1 -0
  13. package/dist/components/pages/forgot-password-page.d.ts +17 -0
  14. package/dist/components/pages/forgot-password-page.js +224 -0
  15. package/dist/components/pages/forgot-password-page.js.map +1 -0
  16. package/dist/components/pages/reset-password-page.d.ts +19 -0
  17. package/dist/components/pages/reset-password-page.js +357 -0
  18. package/dist/components/pages/reset-password-page.js.map +1 -0
  19. package/dist/components/pages/sign-in-page.d.ts +19 -0
  20. package/dist/components/pages/sign-in-page.js +343 -0
  21. package/dist/components/pages/sign-in-page.js.map +1 -0
  22. package/dist/components/pages/sign-up-page.d.ts +18 -0
  23. package/dist/components/pages/sign-up-page.js +360 -0
  24. package/dist/components/pages/sign-up-page.js.map +1 -0
  25. package/dist/components/pages/verify-email-page.d.ts +19 -0
  26. package/dist/components/pages/verify-email-page.js +356 -0
  27. package/dist/components/pages/verify-email-page.js.map +1 -0
  28. package/dist/components/pages/verify-phone-page.d.ts +20 -0
  29. package/dist/components/pages/verify-phone-page.js +368 -0
  30. package/dist/components/pages/verify-phone-page.js.map +1 -0
  31. package/dist/components/reset-password-form.d.ts +16 -0
  32. package/dist/components/reset-password-form.js +142 -0
  33. package/dist/components/reset-password-form.js.map +1 -0
  34. package/dist/components/sign-in.d.ts +16 -0
  35. package/dist/components/sign-in.js +128 -0
  36. package/dist/components/sign-in.js.map +1 -0
  37. package/dist/components/sign-up.d.ts +17 -0
  38. package/dist/components/sign-up.js +179 -0
  39. package/dist/components/sign-up.js.map +1 -0
  40. package/dist/components/verification-form.d.ts +15 -0
  41. package/dist/components/verification-form.js +155 -0
  42. package/dist/components/verification-form.js.map +1 -0
  43. package/dist/index.d.ts +222 -0
  44. package/dist/index.js +1640 -0
  45. package/dist/index.js.map +1 -0
  46. package/package.json +48 -0
@@ -0,0 +1,360 @@
1
+ "use client";
2
+
3
+ // src/components/pages/sign-up-page.tsx
4
+ import { useTranslations as useTranslations2 } from "next-intl";
5
+ import { useState as useState3 } from "react";
6
+
7
+ // src/context/auth-provider.tsx
8
+ import {
9
+ createContext,
10
+ useCallback,
11
+ useContext,
12
+ useEffect,
13
+ useState
14
+ } from "react";
15
+ import { jsx } from "react/jsx-runtime";
16
+ var AuthContext = createContext(null);
17
+ var useAuth = () => {
18
+ const context = useContext(AuthContext);
19
+ if (!context) {
20
+ throw new Error("useAuth must be used within AuthProvider");
21
+ }
22
+ return context;
23
+ };
24
+
25
+ // src/client.ts
26
+ var AuthError = class extends Error {
27
+ code;
28
+ status;
29
+ details;
30
+ constructor(message, code, status, details) {
31
+ super(message);
32
+ this.name = "AuthError";
33
+ this.code = code;
34
+ this.status = status;
35
+ this.details = details;
36
+ }
37
+ };
38
+
39
+ // src/constants/auth.error.codes.ts
40
+ var validCodes = [
41
+ "USER_NOT_FOUND",
42
+ "INVALID_PASSWORD",
43
+ "USER_EXISTS",
44
+ "VERIFICATION_EXPIRED",
45
+ "VERIFICATION_MISMATCH",
46
+ "VERIFICATION_NOT_FOUND",
47
+ "TOO_MANY_ATTEMPTS",
48
+ "REQUIRES_VERIFICATION",
49
+ "UNAUTHORIZED",
50
+ "ACCESS_DENIED",
51
+ "HAS_NO_PASSWORD"
52
+ ];
53
+
54
+ // src/utils/handle-error.ts
55
+ var handleError = (err, setError, t) => {
56
+ if (err instanceof AuthError) {
57
+ let errorKey = "errors.fallback";
58
+ if (err.code) {
59
+ errorKey = `errors.${err.code.toLowerCase()}`;
60
+ } else if (err.message) {
61
+ const messageUpper = err.message.toUpperCase().trim();
62
+ if (validCodes.includes(messageUpper)) {
63
+ errorKey = `errors.${messageUpper.toLowerCase()}`;
64
+ }
65
+ }
66
+ setError(t(errorKey, { defaultValue: err.message }));
67
+ } else {
68
+ setError(err instanceof Error ? err.message : t("errors.fallback"));
69
+ }
70
+ };
71
+
72
+ // src/components/auth-page-layout.tsx
73
+ import { Alert, AlertDescription } from "@mesob/ui/components/alert";
74
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
75
+ var AuthPageLayout = ({
76
+ title,
77
+ description,
78
+ children,
79
+ error,
80
+ footer,
81
+ logoImage
82
+ }) => {
83
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
84
+ /* @__PURE__ */ jsx2("div", { className: "flex size-8 mb-6 w-full items-center justify-center rounded-md", children: /* @__PURE__ */ jsx2("img", { src: logoImage || "", alt: "Jiret", width: 42, height: 42 }) }),
85
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
86
+ /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
87
+ description && /* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
88
+ ] }),
89
+ children,
90
+ error && /* @__PURE__ */ jsx2(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx2(AlertDescription, { children: error }) }),
91
+ /* @__PURE__ */ jsx2("div", { className: "mt-2 w-full", children: footer && /* @__PURE__ */ jsx2("div", { className: "w-full text-center text-sm text-muted-foreground", children: footer }) })
92
+ ] });
93
+ };
94
+
95
+ // src/components/sign-up.tsx
96
+ import { zodResolver } from "@hookform/resolvers/zod";
97
+ import { Button } from "@mesob/ui/components/button";
98
+ import {
99
+ Form,
100
+ FormControl,
101
+ FormField,
102
+ FormItem,
103
+ FormLabel,
104
+ FormMessage
105
+ } from "@mesob/ui/components/form";
106
+ import { Input } from "@mesob/ui/components/input";
107
+ import { Eye, EyeOff } from "lucide-react";
108
+ import { useTranslations } from "next-intl";
109
+ import { useEffect as useEffect2, useMemo, useState as useState2 } from "react";
110
+ import { useForm } from "react-hook-form";
111
+ import { z } from "zod";
112
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
113
+ var isPhone = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
114
+ var SignUp = ({
115
+ onSubmit,
116
+ isLoading = false,
117
+ initialIdentifier
118
+ }) => {
119
+ const t = useTranslations("Auth.signUp");
120
+ const hasInitialIdentifier = !!initialIdentifier;
121
+ const [showPassword, setShowPassword] = useState2(false);
122
+ const [showConfirmPassword, setShowConfirmPassword] = useState2(false);
123
+ const signUpSchema = useMemo(
124
+ () => z.object({
125
+ fullName: z.string().min(1, t("errors.fullNameRequired")),
126
+ identifier: z.string().min(1, t("errors.contactRequired")).refine(
127
+ (val) => {
128
+ if (!val) {
129
+ return false;
130
+ }
131
+ return val.includes("@") || isPhone(val);
132
+ },
133
+ {
134
+ message: t("errors.invalidEmailOrPhone")
135
+ }
136
+ ),
137
+ password: z.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError")),
138
+ confirmPassword: z.string()
139
+ }).refine((data) => data.password === data.confirmPassword, {
140
+ message: t("errors.passwordsMismatch"),
141
+ path: ["confirmPassword"]
142
+ }),
143
+ [t]
144
+ );
145
+ const form = useForm({
146
+ resolver: zodResolver(signUpSchema),
147
+ defaultValues: {
148
+ fullName: "",
149
+ identifier: initialIdentifier || "",
150
+ password: "",
151
+ confirmPassword: ""
152
+ }
153
+ });
154
+ useEffect2(() => {
155
+ if (initialIdentifier) {
156
+ form.setValue("identifier", initialIdentifier);
157
+ }
158
+ }, [initialIdentifier, form]);
159
+ const handleSubmit = form.handleSubmit(async (values) => {
160
+ await onSubmit(values);
161
+ });
162
+ const getIdentifierLabel = () => {
163
+ if (!hasInitialIdentifier) {
164
+ return t("form.accountLabel") || "Email/Phone";
165
+ }
166
+ if (initialIdentifier?.includes("@")) {
167
+ return t("form.emailLabel");
168
+ }
169
+ return t("form.phoneLabel");
170
+ };
171
+ const identifierLabel = getIdentifierLabel();
172
+ return /* @__PURE__ */ jsx3(Form, { ...form, children: /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
173
+ /* @__PURE__ */ jsx3(
174
+ FormField,
175
+ {
176
+ control: form.control,
177
+ name: "fullName",
178
+ render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
179
+ /* @__PURE__ */ jsx3(FormLabel, { children: t("form.fullNameLabel") }),
180
+ /* @__PURE__ */ jsx3(FormControl, { children: /* @__PURE__ */ jsx3(Input, { placeholder: t("form.fullNamePlaceholder"), ...field }) }),
181
+ /* @__PURE__ */ jsx3(FormMessage, {})
182
+ ] })
183
+ }
184
+ ),
185
+ /* @__PURE__ */ jsx3(
186
+ FormField,
187
+ {
188
+ control: form.control,
189
+ name: "identifier",
190
+ render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
191
+ /* @__PURE__ */ jsx3(FormLabel, { className: hasInitialIdentifier ? "block" : void 0, children: identifierLabel }),
192
+ /* @__PURE__ */ jsx3(FormControl, { children: /* @__PURE__ */ jsx3(
193
+ Input,
194
+ {
195
+ type: field.value.includes("@") ? "email" : "tel",
196
+ placeholder: hasInitialIdentifier ? void 0 : t("form.accountPlaceholder") || "Email or phone number",
197
+ ...field,
198
+ disabled: hasInitialIdentifier
199
+ }
200
+ ) }),
201
+ /* @__PURE__ */ jsx3(FormMessage, {})
202
+ ] })
203
+ }
204
+ ),
205
+ /* @__PURE__ */ jsx3(
206
+ FormField,
207
+ {
208
+ control: form.control,
209
+ name: "password",
210
+ render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
211
+ /* @__PURE__ */ jsx3(FormLabel, { children: t("form.passwordLabel") }),
212
+ /* @__PURE__ */ jsx3(FormControl, { children: /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
213
+ /* @__PURE__ */ jsx3(
214
+ Input,
215
+ {
216
+ type: showPassword ? "text" : "password",
217
+ placeholder: t("form.passwordPlaceholder"),
218
+ ...field
219
+ }
220
+ ),
221
+ /* @__PURE__ */ jsx3(
222
+ "button",
223
+ {
224
+ type: "button",
225
+ onClick: () => setShowPassword(!showPassword),
226
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
227
+ children: showPassword ? /* @__PURE__ */ jsx3(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx3(Eye, { className: "h-4 w-4" })
228
+ }
229
+ )
230
+ ] }) }),
231
+ /* @__PURE__ */ jsx3(FormMessage, {})
232
+ ] })
233
+ }
234
+ ),
235
+ /* @__PURE__ */ jsx3(
236
+ FormField,
237
+ {
238
+ control: form.control,
239
+ name: "confirmPassword",
240
+ render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
241
+ /* @__PURE__ */ jsx3(FormLabel, { children: t("form.confirmPasswordLabel") }),
242
+ /* @__PURE__ */ jsx3(FormControl, { children: /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
243
+ /* @__PURE__ */ jsx3(
244
+ Input,
245
+ {
246
+ type: showConfirmPassword ? "text" : "password",
247
+ placeholder: t("form.passwordPlaceholder"),
248
+ ...field
249
+ }
250
+ ),
251
+ /* @__PURE__ */ jsx3(
252
+ "button",
253
+ {
254
+ type: "button",
255
+ onClick: () => setShowConfirmPassword(!showConfirmPassword),
256
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
257
+ children: showConfirmPassword ? /* @__PURE__ */ jsx3(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx3(Eye, { className: "h-4 w-4" })
258
+ }
259
+ )
260
+ ] }) }),
261
+ /* @__PURE__ */ jsx3(FormMessage, {})
262
+ ] })
263
+ }
264
+ ),
265
+ /* @__PURE__ */ jsx3(Button, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.submit") })
266
+ ] }) });
267
+ };
268
+
269
+ // src/components/pages/sign-up-page.tsx
270
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
271
+ var isPhone2 = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
272
+ var SignUpPage = ({
273
+ onNavigate,
274
+ linkComponent: Link,
275
+ links,
276
+ initialIdentifier,
277
+ logoImage
278
+ }) => {
279
+ const t = useTranslations2("Auth.signUp");
280
+ const { client, setAuth } = useAuth();
281
+ const [isLoading, setIsLoading] = useState3(false);
282
+ const [error, setError] = useState3(null);
283
+ const signInLink = links?.signIn || "/auth/sign-in";
284
+ const handleSubmit = async (values) => {
285
+ setIsLoading(true);
286
+ setError(null);
287
+ try {
288
+ const identifier = values.identifier;
289
+ const usingPhone = isPhone2(identifier);
290
+ const res = usingPhone ? await client.signUpWithPhone({
291
+ phone: identifier,
292
+ password: values.password,
293
+ fullName: values.fullName,
294
+ handle: values.handle
295
+ }) : await client.signUpWithEmail({
296
+ email: identifier,
297
+ password: values.password,
298
+ fullName: values.fullName,
299
+ handle: values.handle
300
+ });
301
+ if ("verificationId" in res && res.verificationId) {
302
+ if (usingPhone) {
303
+ onNavigate(
304
+ `/auth/verify-phone?context=sign-up&verificationId=${res.verificationId}&phone=${encodeURIComponent(identifier)}`
305
+ );
306
+ } else {
307
+ onNavigate(
308
+ `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(identifier)}`
309
+ );
310
+ }
311
+ return;
312
+ }
313
+ if ("user" in res && "session" in res) {
314
+ setAuth(res);
315
+ }
316
+ onNavigate("/dashboard");
317
+ } catch (err) {
318
+ handleError(err, setError, t);
319
+ } finally {
320
+ setIsLoading(false);
321
+ }
322
+ };
323
+ return /* @__PURE__ */ jsx4(
324
+ AuthPageLayout,
325
+ {
326
+ title: t("title"),
327
+ description: t("description"),
328
+ error,
329
+ logoImage,
330
+ footer: /* @__PURE__ */ jsxs3("p", { children: [
331
+ t("footer.hasAccount"),
332
+ " ",
333
+ Link ? /* @__PURE__ */ jsx4(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.signInCta") }) : /* @__PURE__ */ jsx4(
334
+ "a",
335
+ {
336
+ href: signInLink,
337
+ onClick: (e) => {
338
+ e.preventDefault();
339
+ onNavigate(signInLink);
340
+ },
341
+ className: "text-primary hover:underline",
342
+ children: t("footer.signInCta")
343
+ }
344
+ )
345
+ ] }),
346
+ children: /* @__PURE__ */ jsx4(
347
+ SignUp,
348
+ {
349
+ onSubmit: handleSubmit,
350
+ isLoading,
351
+ initialIdentifier
352
+ }
353
+ )
354
+ }
355
+ );
356
+ };
357
+ export {
358
+ SignUpPage
359
+ };
360
+ //# sourceMappingURL=sign-up-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/pages/sign-up-page.tsx","../../../src/context/auth-provider.tsx","../../../src/client.ts","../../../src/constants/auth.error.codes.ts","../../../src/utils/handle-error.ts","../../../src/components/auth-page-layout.tsx","../../../src/components/sign-up.tsx"],"sourcesContent":["'use client';\n\nimport { useTranslations } from 'next-intl';\nimport type { ComponentProps } from 'react';\nimport { useState } from 'react';\nimport { useAuth } from '../../context/auth-provider';\nimport { handleError } from '../../utils/handle-error';\nimport { AuthPageLayout } from '../auth-page-layout';\nimport { SignUp } from '../sign-up';\n\nconst isPhone = (s: string) => /^\\+?[0-9()[\\]\\s-]{6,}$/.test(s);\n\ntype SignUpFormValues = {\n fullName: string;\n identifier: string;\n handle?: string;\n password: string;\n confirmPassword: string;\n};\n\ntype SignUpPageProps = {\n locale?: string;\n onNavigate: (path: string) => void;\n linkComponent?: React.ComponentType<ComponentProps<'a'> & { href: string }>;\n links?: {\n signIn?: string;\n };\n initialIdentifier?: string;\n logoImage?: string;\n};\n\nexport const SignUpPage = ({\n onNavigate,\n linkComponent: Link,\n links,\n initialIdentifier,\n logoImage,\n}: SignUpPageProps) => {\n const t = useTranslations('Auth.signUp');\n const { client, setAuth } = useAuth();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const signInLink = links?.signIn || '/auth/sign-in';\n\n const handleSubmit = async (values: SignUpFormValues) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const identifier = values.identifier;\n const usingPhone = isPhone(identifier);\n\n const res = usingPhone\n ? await client.signUpWithPhone({\n phone: identifier,\n password: values.password,\n fullName: values.fullName,\n handle: values.handle,\n })\n : await client.signUpWithEmail({\n email: identifier,\n password: values.password,\n fullName: values.fullName,\n handle: values.handle,\n });\n\n if ('verificationId' in res && res.verificationId) {\n if (usingPhone) {\n onNavigate(\n `/auth/verify-phone?context=sign-up&verificationId=${res.verificationId}&phone=${encodeURIComponent(identifier)}`,\n );\n } else {\n onNavigate(\n `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(identifier)}`,\n );\n }\n return;\n }\n\n if ('user' in res && 'session' in res) {\n setAuth(res);\n }\n onNavigate('/dashboard');\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n };\n\n return (\n <AuthPageLayout\n title={t('title')}\n description={t('description')}\n error={error}\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 <SignUp\n onSubmit={handleSubmit}\n isLoading={isLoading}\n initialIdentifier={initialIdentifier}\n />\n </AuthPageLayout>\n );\n};\n","'use client';\n\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport type { AuthClient } from '../client';\nimport type { AuthResponse, Session, User } from '../types';\n\ntype AuthContextValue = {\n user: User | null;\n session: Session | null;\n loading: boolean;\n error: Error | null;\n client: AuthClient;\n refresh: () => Promise<void>;\n setAuth: (data: AuthResponse) => void;\n};\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\nexport const useAuth = () => {\n const context = useContext(AuthContext);\n if (!context) {\n throw new Error('useAuth must be used within AuthProvider');\n }\n return context;\n};\n\ntype AuthProviderProps = {\n client: AuthClient;\n children: ReactNode;\n};\n\nexport const AuthProvider = ({ client, children }: AuthProviderProps) => {\n const [user, setUser] = useState<User | null>(null);\n const [session, setSession] = useState<Session | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const refresh = useCallback(async () => {\n try {\n setLoading(true);\n setError(null);\n const data = await client.getSession();\n setUser(data.user);\n setSession(data.session);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error('Failed to fetch session'),\n );\n setUser(null);\n setSession(null);\n } finally {\n setLoading(false);\n }\n }, [client]);\n\n const setAuth = useCallback((data: AuthResponse) => {\n setUser(data.user);\n setSession(data.session);\n setError(null);\n setLoading(false);\n }, []);\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n return (\n <AuthContext.Provider\n value={{\n user,\n session,\n loading,\n error,\n client,\n refresh,\n setAuth,\n }}\n >\n {children}\n </AuthContext.Provider>\n );\n};\n","import type {\n AuthErrorCode,\n AuthErrorResponse,\n AuthResponse,\n SessionResponse,\n User,\n VerificationResponse,\n} from './types';\n\n// Backend returns error code in 'error' field (AUTH_ERRORS values)\n// or in 'code' field, message in 'message' or 'error' field\nconst validErrorCodes: readonly 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] as const;\n\nexport class AuthError extends Error {\n code?: AuthErrorCode;\n status?: number;\n details?: Record<string, unknown>;\n\n constructor(\n message: string,\n code?: AuthErrorCode,\n status?: number,\n details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'AuthError';\n this.code = code;\n this.status = status;\n this.details = details;\n }\n}\n\nexport type AuthClientConfig = {\n baseURL: string;\n};\n\nexport class AuthClient {\n private baseURL: string;\n\n constructor(config: AuthClientConfig) {\n this.baseURL = config.baseURL.replace(/\\/$/, '');\n }\n\n private async request<T>(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<T> {\n const url = `${this.baseURL}${endpoint}`;\n const response = await fetch(url, {\n ...options,\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n });\n if (!response.ok) {\n const text = await response.text();\n let errorData: AuthErrorResponse;\n try {\n errorData = JSON.parse(text);\n } catch {\n errorData = { error: 'Unknown error', message: text };\n }\n\n // Extract error code from code, error, or message field\n // Backend returns error codes in 'error' field (e.g., { error: 'INVALID_PASSWORD' })\n const potentialCode =\n errorData.code ||\n (typeof errorData.error === 'string' ? errorData.error : null) ||\n (typeof errorData.message === 'string' ? errorData.message : null);\n const upperCode = potentialCode?.toUpperCase().trim();\n const errorCode =\n upperCode && validErrorCodes.includes(upperCode as AuthErrorCode)\n ? (upperCode as AuthErrorCode)\n : undefined;\n const errorMessage =\n errorData.message || errorData.error || 'Request failed';\n\n throw new AuthError(\n errorMessage,\n errorCode as AuthErrorCode | undefined,\n response.status,\n errorData.details,\n );\n }\n\n const data = await response.json();\n return data;\n }\n\n signUpWithEmail(data: {\n email: string;\n password: string;\n fullName: string;\n handle?: string;\n }): Promise<AuthResponse | VerificationResponse> {\n return this.request<AuthResponse | VerificationResponse>('/sign-up', {\n method: 'POST',\n body: JSON.stringify({\n email: data.email,\n password: data.password,\n fullName: data.fullName,\n handle: data.handle,\n }),\n });\n }\n\n signUpWithPhone(data: {\n phone: string;\n password: string;\n fullName: string;\n handle?: string;\n }): Promise<AuthResponse | VerificationResponse> {\n return this.request<AuthResponse | VerificationResponse>('/sign-up', {\n method: 'POST',\n body: JSON.stringify({\n phone: data.phone,\n password: data.password,\n fullName: data.fullName,\n handle: data.handle,\n }),\n });\n }\n\n checkUser(data: { identifier: string }): Promise<{ exists: boolean }> {\n return this.request<{ exists: boolean }>('/check-user', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n signInWithPassword(data: {\n identifier: string;\n password: string;\n }): Promise<AuthResponse | VerificationResponse> {\n return this.request<AuthResponse | VerificationResponse>('/sign-in', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n signOut(): Promise<{ message: string }> {\n return this.request<{ message: string }>('/sign-out', {\n method: 'POST',\n });\n }\n\n requestEmailVerification(data?: {\n email?: string;\n }): Promise<{ verificationId: string }> {\n return this.request<{ verificationId: string }>(\n '/email/verification/request',\n {\n method: 'POST',\n body: JSON.stringify(data || {}),\n },\n );\n }\n\n verifyEmail(data: {\n verificationId: string;\n code: string;\n }): Promise<AuthResponse> {\n return this.request<AuthResponse>('/email/verification/confirm', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n resendVerification(_verificationId: string): Promise<{\n verificationId: string;\n }> {\n // For email, request new verification\n return this.requestEmailVerification();\n }\n\n requestPhoneOtp(data: {\n phone: string;\n context: 'sign-up' | 'sign-in' | 'change-phone';\n }): Promise<{ verificationId: string }> {\n return this.request<{ verificationId: string }>(\n '/phone/verification/request',\n {\n method: 'POST',\n body: JSON.stringify(data),\n },\n );\n }\n\n verifyPhoneOtp(data: {\n verificationId: string;\n code: string;\n context: 'sign-up' | 'sign-in' | 'change-phone';\n }): Promise<\n AuthResponse | { user: User | null; session: null; verified: boolean }\n > {\n return this.request('/phone/verification/confirm', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n forgotPassword(data: { identifier: string }): Promise<{\n message: string;\n }> {\n return this.request<{ message: string }>('/password/forgot', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n resetPassword(data: {\n verificationId: string;\n code: string;\n password: string;\n }): Promise<AuthResponse> {\n return this.request<AuthResponse>('/password/reset', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n changePassword(data: {\n currentPassword: string;\n newPassword: string;\n }): Promise<{ message: string }> {\n return this.request<{ message: string }>('/password/change', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n getSession(): Promise<SessionResponse> {\n return this.request<SessionResponse>('/session', {\n method: 'GET',\n });\n }\n}\n","export const validCodes = [\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];\n","import type { _Translator } from 'next-intl';\nimport { AuthError } from '../client';\nimport { validCodes } from '../constants/auth.error.codes';\n\nexport const handleError = (\n err: any,\n setError: (error: string | null) => void,\n t: _Translator<Record<string, any>, string>,\n) => {\n if (err instanceof AuthError) {\n let errorKey = 'errors.fallback';\n if (err.code) {\n errorKey = `errors.${err.code.toLowerCase()}`;\n } else if (err.message) {\n // Fallback: try to extract error code from message\n const messageUpper = err.message.toUpperCase().trim();\n\n if (validCodes.includes(messageUpper)) {\n errorKey = `errors.${messageUpper.toLowerCase()}`;\n }\n }\n setError(t(errorKey, { defaultValue: err.message }));\n } else {\n setError(err instanceof Error ? err.message : t('errors.fallback'));\n }\n};\n","'use client';\n\nimport { Alert, AlertDescription } from '@mesob/ui/components/alert';\nimport type { ReactNode } from 'react';\n\ntype AuthPageLayoutProps = {\n title: string;\n description?: string;\n children: ReactNode;\n error?: string | null;\n footer?: ReactNode;\n logoImage?: string;\n};\n\nexport const AuthPageLayout = ({\n title,\n description,\n children,\n error,\n footer,\n logoImage,\n}: AuthPageLayoutProps) => {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex size-8 mb-6 w-full items-center justify-center rounded-md\">\n {/** biome-ignore lint/performance/noImgElement: logo image */}\n <img src={logoImage || ''} alt=\"Jiret\" width={42} height={42} />\n </div>\n <div className=\"text-center\">\n <h1 className=\"text-2xl font-bold tracking-tight\">{title}</h1>\n {description && (\n <p className=\"mt-2 text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n\n {children}\n\n {error && (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n <div className=\"mt-2 w-full\">\n {footer && (\n <div className=\"w-full text-center text-sm text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>\n </div>\n );\n};\n","'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Button } from '@mesob/ui/components/button';\nimport {\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@mesob/ui/components/form';\nimport { Input } from '@mesob/ui/components/input';\nimport { Eye, EyeOff } from 'lucide-react';\nimport { useTranslations } from 'next-intl';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\n\nconst isPhone = (s: string) => /^\\+?[0-9()[\\]\\s-]{6,}$/.test(s);\n\ntype SignUpFormValues = {\n fullName: string;\n identifier: string;\n handle?: string;\n password: string;\n confirmPassword: string;\n};\n\ntype SignUpProps = {\n onSubmit: (values: SignUpFormValues) => Promise<void> | void;\n isLoading?: boolean;\n initialIdentifier?: string;\n};\n\nexport const SignUp = ({\n onSubmit,\n isLoading = false,\n initialIdentifier,\n}: SignUpProps) => {\n const t = useTranslations('Auth.signUp');\n const hasInitialIdentifier = !!initialIdentifier;\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmPassword, setShowConfirmPassword] = useState(false);\n\n const signUpSchema = useMemo(\n () =>\n z\n .object({\n fullName: z.string().min(1, t('errors.fullNameRequired')),\n identifier: z\n .string()\n .min(1, t('errors.contactRequired'))\n .refine(\n (val) => {\n if (!val) {\n return false;\n }\n return val.includes('@') || isPhone(val);\n },\n {\n message: t('errors.invalidEmailOrPhone'),\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 [t],\n );\n\n const form = useForm<SignUpFormValues>({\n resolver: zodResolver(signUpSchema),\n defaultValues: {\n fullName: '',\n identifier: initialIdentifier || '',\n password: '',\n confirmPassword: '',\n },\n });\n\n useEffect(() => {\n if (initialIdentifier) {\n form.setValue('identifier', initialIdentifier);\n }\n }, [initialIdentifier, form]);\n\n const handleSubmit = form.handleSubmit(async (values) => {\n await onSubmit(values);\n });\n\n const getIdentifierLabel = () => {\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\n return (\n <Form {...form}>\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"fullName\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.fullNameLabel')}</FormLabel>\n <FormControl>\n <Input placeholder={t('form.fullNamePlaceholder')} {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={form.control}\n name=\"identifier\"\n render={({ field }) => (\n <FormItem>\n <FormLabel className={hasInitialIdentifier ? 'block' : undefined}>\n {identifierLabel}\n </FormLabel>\n <FormControl>\n <Input\n type={field.value.includes('@') ? 'email' : 'tel'}\n placeholder={\n hasInitialIdentifier\n ? undefined\n : t('form.accountPlaceholder') || 'Email or phone number'\n }\n {...field}\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 <FormControl>\n <div className=\"relative\">\n <Input\n type={showPassword ? 'text' : 'password'}\n placeholder={t('form.passwordPlaceholder')}\n {...field}\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword(!showPassword)}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n >\n {showPassword ? (\n <EyeOff className=\"h-4 w-4\" />\n ) : (\n <Eye className=\"h-4 w-4\" />\n )}\n </button>\n </div>\n </FormControl>\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 <FormControl>\n <div className=\"relative\">\n <Input\n type={showConfirmPassword ? 'text' : 'password'}\n placeholder={t('form.passwordPlaceholder')}\n {...field}\n />\n <button\n type=\"button\"\n onClick={() => setShowConfirmPassword(!showConfirmPassword)}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n >\n {showConfirmPassword ? (\n <EyeOff className=\"h-4 w-4\" />\n ) : (\n <Eye className=\"h-4 w-4\" />\n )}\n </button>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <Button type=\"submit\" className=\"w-full\" disabled={isLoading}>\n {isLoading ? t('form.submitting') : t('form.submit')}\n </Button>\n </form>\n </Form>\n );\n};\n"],"mappings":"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","names":["useTranslations","useState","jsx","useEffect","useState","jsx","jsxs","jsx","jsxs","isPhone","useTranslations","useState"]}
@@ -0,0 +1,19 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ComponentProps } from 'react';
3
+
4
+ type VerifyEmailPageProps = {
5
+ locale?: string;
6
+ verificationId: string;
7
+ email: string;
8
+ onNavigate: (path: string) => void;
9
+ linkComponent?: React.ComponentType<ComponentProps<'a'> & {
10
+ href: string;
11
+ }>;
12
+ links?: {
13
+ signIn?: string;
14
+ };
15
+ logoImage?: string;
16
+ };
17
+ declare const VerifyEmailPage: ({ verificationId, onNavigate, linkComponent: Link, links, email, logoImage, }: VerifyEmailPageProps) => react_jsx_runtime.JSX.Element;
18
+
19
+ export { VerifyEmailPage };