@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.
- package/dist/components/auth-card.d.ts +9 -0
- package/dist/components/auth-card.js +11 -0
- package/dist/components/auth-card.js.map +1 -0
- package/dist/components/auth-page-layout.d.ts +14 -0
- package/dist/components/auth-page-layout.js +28 -0
- package/dist/components/auth-page-layout.js.map +1 -0
- package/dist/components/countdown.d.ts +10 -0
- package/dist/components/countdown.js +57 -0
- package/dist/components/countdown.js.map +1 -0
- package/dist/components/forgot-password.d.ts +13 -0
- package/dist/components/forgot-password.js +67 -0
- package/dist/components/forgot-password.js.map +1 -0
- package/dist/components/pages/forgot-password-page.d.ts +17 -0
- package/dist/components/pages/forgot-password-page.js +224 -0
- package/dist/components/pages/forgot-password-page.js.map +1 -0
- package/dist/components/pages/reset-password-page.d.ts +19 -0
- package/dist/components/pages/reset-password-page.js +357 -0
- package/dist/components/pages/reset-password-page.js.map +1 -0
- package/dist/components/pages/sign-in-page.d.ts +19 -0
- package/dist/components/pages/sign-in-page.js +343 -0
- package/dist/components/pages/sign-in-page.js.map +1 -0
- package/dist/components/pages/sign-up-page.d.ts +18 -0
- package/dist/components/pages/sign-up-page.js +360 -0
- package/dist/components/pages/sign-up-page.js.map +1 -0
- package/dist/components/pages/verify-email-page.d.ts +19 -0
- package/dist/components/pages/verify-email-page.js +356 -0
- package/dist/components/pages/verify-email-page.js.map +1 -0
- package/dist/components/pages/verify-phone-page.d.ts +20 -0
- package/dist/components/pages/verify-phone-page.js +368 -0
- package/dist/components/pages/verify-phone-page.js.map +1 -0
- package/dist/components/reset-password-form.d.ts +16 -0
- package/dist/components/reset-password-form.js +142 -0
- package/dist/components/reset-password-form.js.map +1 -0
- package/dist/components/sign-in.d.ts +16 -0
- package/dist/components/sign-in.js +128 -0
- package/dist/components/sign-in.js.map +1 -0
- package/dist/components/sign-up.d.ts +17 -0
- package/dist/components/sign-up.js +179 -0
- package/dist/components/sign-up.js.map +1 -0
- package/dist/components/verification-form.d.ts +15 -0
- package/dist/components/verification-form.js +155 -0
- package/dist/components/verification-form.js.map +1 -0
- package/dist/index.d.ts +222 -0
- package/dist/index.js +1640 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/components/pages/sign-in-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-in.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 { 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 SignIn = ({
|
|
114
|
+
onSubmit,
|
|
115
|
+
isLoading = false,
|
|
116
|
+
identifier = "",
|
|
117
|
+
step = "identifier",
|
|
118
|
+
onBack: _onBack
|
|
119
|
+
}) => {
|
|
120
|
+
const t = useTranslations("Auth.signIn");
|
|
121
|
+
const [showPassword, setShowPassword] = useState2(false);
|
|
122
|
+
const identifierSchema = useMemo(
|
|
123
|
+
() => z.object({
|
|
124
|
+
account: z.string().min(1, t("errors.accountRequired")).email(t("errors.invalidEmail"))
|
|
125
|
+
}),
|
|
126
|
+
[t]
|
|
127
|
+
);
|
|
128
|
+
const passwordSchema = useMemo(
|
|
129
|
+
() => z.object({
|
|
130
|
+
password: z.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError"))
|
|
131
|
+
}),
|
|
132
|
+
[t]
|
|
133
|
+
);
|
|
134
|
+
const identifierForm = useForm({
|
|
135
|
+
resolver: zodResolver(identifierSchema),
|
|
136
|
+
defaultValues: {
|
|
137
|
+
account: identifier
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
const passwordForm = useForm({
|
|
141
|
+
resolver: zodResolver(passwordSchema),
|
|
142
|
+
defaultValues: {
|
|
143
|
+
password: ""
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
const handleIdentifierSubmit = identifierForm.handleSubmit(async (values) => {
|
|
147
|
+
await onSubmit({ account: values.account, password: "" }, "identifier");
|
|
148
|
+
});
|
|
149
|
+
const handlePasswordSubmit = passwordForm.handleSubmit(async (values) => {
|
|
150
|
+
await onSubmit(
|
|
151
|
+
{ account: identifier, password: values.password },
|
|
152
|
+
"password"
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
if (step === "password") {
|
|
156
|
+
return /* @__PURE__ */ jsx3(Form, { ...passwordForm, children: /* @__PURE__ */ jsxs2("form", { onSubmit: handlePasswordSubmit, className: "space-y-4", children: [
|
|
157
|
+
/* @__PURE__ */ jsxs2("div", { className: "text-center", children: [
|
|
158
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground mb-2", children: t("form.enterPasswordFor") }),
|
|
159
|
+
/* @__PURE__ */ jsx3("p", { className: "font-bold", children: identifier })
|
|
160
|
+
] }),
|
|
161
|
+
/* @__PURE__ */ jsx3(
|
|
162
|
+
FormField,
|
|
163
|
+
{
|
|
164
|
+
control: passwordForm.control,
|
|
165
|
+
name: "password",
|
|
166
|
+
render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
|
|
167
|
+
/* @__PURE__ */ jsx3(FormLabel, { children: t("form.passwordLabel") }),
|
|
168
|
+
/* @__PURE__ */ jsx3(FormControl, { children: /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
|
|
169
|
+
/* @__PURE__ */ jsx3(
|
|
170
|
+
Input,
|
|
171
|
+
{
|
|
172
|
+
type: showPassword ? "text" : "password",
|
|
173
|
+
placeholder: t("form.passwordPlaceholder"),
|
|
174
|
+
...field
|
|
175
|
+
}
|
|
176
|
+
),
|
|
177
|
+
/* @__PURE__ */ jsx3(
|
|
178
|
+
"button",
|
|
179
|
+
{
|
|
180
|
+
type: "button",
|
|
181
|
+
onClick: () => setShowPassword(!showPassword),
|
|
182
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
|
|
183
|
+
children: showPassword ? /* @__PURE__ */ jsx3(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx3(Eye, { className: "h-4 w-4" })
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
] }) }),
|
|
187
|
+
/* @__PURE__ */ jsx3(FormMessage, {})
|
|
188
|
+
] })
|
|
189
|
+
}
|
|
190
|
+
),
|
|
191
|
+
/* @__PURE__ */ jsx3(Button, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.submit") })
|
|
192
|
+
] }) });
|
|
193
|
+
}
|
|
194
|
+
return /* @__PURE__ */ jsx3(Form, { ...identifierForm, children: /* @__PURE__ */ jsxs2("form", { onSubmit: handleIdentifierSubmit, className: "space-y-4", children: [
|
|
195
|
+
/* @__PURE__ */ jsx3(
|
|
196
|
+
FormField,
|
|
197
|
+
{
|
|
198
|
+
control: identifierForm.control,
|
|
199
|
+
name: "account",
|
|
200
|
+
render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
|
|
201
|
+
/* @__PURE__ */ jsx3(FormLabel, { children: t("form.accountLabel") }),
|
|
202
|
+
/* @__PURE__ */ jsx3(FormControl, { children: /* @__PURE__ */ jsx3(
|
|
203
|
+
Input,
|
|
204
|
+
{
|
|
205
|
+
type: "text",
|
|
206
|
+
placeholder: t("form.accountPlaceholder"),
|
|
207
|
+
...field
|
|
208
|
+
}
|
|
209
|
+
) }),
|
|
210
|
+
/* @__PURE__ */ jsx3(FormMessage, {})
|
|
211
|
+
] })
|
|
212
|
+
}
|
|
213
|
+
),
|
|
214
|
+
/* @__PURE__ */ jsx3(Button, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.continue") })
|
|
215
|
+
] }) });
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// src/components/pages/sign-in-page.tsx
|
|
219
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
220
|
+
var isPhone = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
|
|
221
|
+
var SignInPage = ({
|
|
222
|
+
redirectUrl,
|
|
223
|
+
onNavigate,
|
|
224
|
+
linkComponent: Link,
|
|
225
|
+
links,
|
|
226
|
+
logoImage
|
|
227
|
+
}) => {
|
|
228
|
+
const t = useTranslations2("Auth.signIn");
|
|
229
|
+
const { client, setAuth } = useAuth();
|
|
230
|
+
const [isLoading, setIsLoading] = useState3(false);
|
|
231
|
+
const [error, setError] = useState3(null);
|
|
232
|
+
const [step, setStep] = useState3("identifier");
|
|
233
|
+
const [identifier, setIdentifier] = useState3("");
|
|
234
|
+
const defaultRedirect = redirectUrl || "/dashboard";
|
|
235
|
+
const forgotPasswordLink = links?.forgotPassword || "/auth/forgot-password";
|
|
236
|
+
const signUpLink = links?.signUp || "/auth/sign-up";
|
|
237
|
+
const handleSubmit = async (values, currentStep) => {
|
|
238
|
+
setIsLoading(true);
|
|
239
|
+
setError(null);
|
|
240
|
+
try {
|
|
241
|
+
if (currentStep === "identifier") {
|
|
242
|
+
const checkResult = await client.checkUser({
|
|
243
|
+
identifier: values.account
|
|
244
|
+
});
|
|
245
|
+
if (checkResult.exists) {
|
|
246
|
+
setIdentifier(values.account);
|
|
247
|
+
setStep("password");
|
|
248
|
+
} else {
|
|
249
|
+
const email = isPhone(values.account) ? "" : values.account;
|
|
250
|
+
if (email) {
|
|
251
|
+
onNavigate(`${signUpLink}?email=${encodeURIComponent(email)}`);
|
|
252
|
+
} else {
|
|
253
|
+
onNavigate(
|
|
254
|
+
`${signUpLink}?phone=${encodeURIComponent(values.account)}`
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
const res = await client.signInWithPassword({
|
|
261
|
+
identifier,
|
|
262
|
+
password: values.password
|
|
263
|
+
});
|
|
264
|
+
if ("verificationId" in res && res.verificationId) {
|
|
265
|
+
const verifyPath = isPhone(identifier) ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(identifier)}` : `/auth/verify-email?verificationId=${res.verificationId}`;
|
|
266
|
+
onNavigate(verifyPath);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if ("user" in res && "session" in res) {
|
|
270
|
+
setAuth(res);
|
|
271
|
+
}
|
|
272
|
+
onNavigate(defaultRedirect);
|
|
273
|
+
}
|
|
274
|
+
} catch (err) {
|
|
275
|
+
handleError(err, setError, t);
|
|
276
|
+
} finally {
|
|
277
|
+
setIsLoading(false);
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
const handleBack = () => {
|
|
281
|
+
setStep("identifier");
|
|
282
|
+
setIdentifier("");
|
|
283
|
+
setError(null);
|
|
284
|
+
};
|
|
285
|
+
const isStepPassword = step === "password";
|
|
286
|
+
return /* @__PURE__ */ jsx4("div", { className: "space-y-4", children: /* @__PURE__ */ jsx4(
|
|
287
|
+
AuthPageLayout,
|
|
288
|
+
{
|
|
289
|
+
title: t("title"),
|
|
290
|
+
description: isStepPassword ? void 0 : t("description"),
|
|
291
|
+
error,
|
|
292
|
+
logoImage,
|
|
293
|
+
footer: /* @__PURE__ */ jsxs3(
|
|
294
|
+
"div",
|
|
295
|
+
{
|
|
296
|
+
className: "flex items-center justify-center w-full gap-2",
|
|
297
|
+
style: {
|
|
298
|
+
justifyContent: isStepPassword ? "space-between" : "center"
|
|
299
|
+
},
|
|
300
|
+
children: [
|
|
301
|
+
isStepPassword && // biome-ignore lint/a11y/useKeyWithClickEvents: change account
|
|
302
|
+
/* @__PURE__ */ jsx4(
|
|
303
|
+
"p",
|
|
304
|
+
{
|
|
305
|
+
className: "text-primary inline-block cursor-pointer hover:underline",
|
|
306
|
+
onClick: handleBack,
|
|
307
|
+
children: t("changeAccount")
|
|
308
|
+
}
|
|
309
|
+
),
|
|
310
|
+
Link ? /* @__PURE__ */ jsx4(
|
|
311
|
+
Link,
|
|
312
|
+
{
|
|
313
|
+
href: forgotPasswordLink,
|
|
314
|
+
className: "text-primary inline-block hover:underline",
|
|
315
|
+
children: t("footer.forgotPassword")
|
|
316
|
+
}
|
|
317
|
+
) : /* @__PURE__ */ jsx4(
|
|
318
|
+
"a",
|
|
319
|
+
{
|
|
320
|
+
href: forgotPasswordLink,
|
|
321
|
+
className: "text-primary inline-block hover:underline",
|
|
322
|
+
children: t("footer.forgotPassword")
|
|
323
|
+
}
|
|
324
|
+
)
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
),
|
|
328
|
+
children: /* @__PURE__ */ jsx4(
|
|
329
|
+
SignIn,
|
|
330
|
+
{
|
|
331
|
+
onSubmit: handleSubmit,
|
|
332
|
+
isLoading,
|
|
333
|
+
identifier,
|
|
334
|
+
step
|
|
335
|
+
}
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
) });
|
|
339
|
+
};
|
|
340
|
+
export {
|
|
341
|
+
SignInPage
|
|
342
|
+
};
|
|
343
|
+
//# sourceMappingURL=sign-in-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/pages/sign-in-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-in.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 { SignIn } from '../sign-in';\n\nconst isPhone = (s: string) => /^\\+?[0-9()[\\]\\s-]{6,}$/.test(s);\n\ntype SignInPageProps = {\n locale?: string;\n redirectUrl?: string;\n onNavigate: (path: string) => void;\n linkComponent?: React.ComponentType<ComponentProps<'a'> & { href: string }>;\n links?: {\n forgotPassword?: string;\n signUp?: string;\n };\n logoImage?: string;\n};\n\nexport const SignInPage = ({\n redirectUrl,\n onNavigate,\n linkComponent: Link,\n links,\n logoImage,\n}: SignInPageProps) => {\n const t = useTranslations('Auth.signIn');\n const { client, setAuth } = useAuth();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [step, setStep] = useState<'identifier' | 'password'>('identifier');\n const [identifier, setIdentifier] = useState<string>('');\n\n const defaultRedirect = redirectUrl || '/dashboard';\n const forgotPasswordLink = links?.forgotPassword || '/auth/forgot-password';\n const signUpLink = links?.signUp || '/auth/sign-up';\n\n const handleSubmit = async (\n values: { account: string; password: string },\n currentStep: 'identifier' | 'password',\n ) => {\n setIsLoading(true);\n setError(null);\n\n try {\n if (currentStep === 'identifier') {\n const checkResult = await client.checkUser({\n identifier: values.account,\n });\n\n if (checkResult.exists) {\n setIdentifier(values.account);\n setStep('password');\n } else {\n const email = isPhone(values.account) ? '' : values.account;\n if (email) {\n onNavigate(`${signUpLink}?email=${encodeURIComponent(email)}`);\n } else {\n onNavigate(\n `${signUpLink}?phone=${encodeURIComponent(values.account)}`,\n );\n }\n return;\n }\n } else {\n const res = await client.signInWithPassword({\n identifier,\n password: values.password,\n });\n\n if ('verificationId' in res && res.verificationId) {\n const verifyPath = isPhone(identifier)\n ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(identifier)}`\n : `/auth/verify-email?verificationId=${res.verificationId}`;\n onNavigate(verifyPath);\n return;\n }\n\n if ('user' in res && 'session' in res) {\n setAuth(res);\n }\n onNavigate(defaultRedirect);\n }\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleBack = () => {\n setStep('identifier');\n setIdentifier('');\n setError(null);\n };\n\n const isStepPassword = step === 'password';\n\n return (\n <div className=\"space-y-4\">\n <AuthPageLayout\n title={t('title')}\n description={isStepPassword ? undefined : t('description')}\n error={error}\n logoImage={logoImage}\n footer={\n <div\n className=\"flex items-center justify-center w-full gap-2\"\n style={{\n justifyContent: isStepPassword ? 'space-between' : 'center',\n }}\n >\n {isStepPassword && (\n // biome-ignore lint/a11y/useKeyWithClickEvents: change account\n <p\n className=\"text-primary inline-block cursor-pointer hover:underline\"\n onClick={handleBack}\n >\n {t('changeAccount')}\n </p>\n )}\n\n {Link ? (\n <Link\n href={forgotPasswordLink}\n className=\"text-primary inline-block hover:underline\"\n >\n {t('footer.forgotPassword')}\n </Link>\n ) : (\n <a\n href={forgotPasswordLink}\n className=\"text-primary inline-block hover:underline\"\n >\n {t('footer.forgotPassword')}\n </a>\n )}\n </div>\n }\n >\n <SignIn\n onSubmit={handleSubmit}\n isLoading={isLoading}\n identifier={identifier}\n step={step}\n />\n </AuthPageLayout>\n </div>\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 { useMemo, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\n\ntype SignInFormValues = {\n account: string;\n password: string;\n};\n\ntype SignInProps = {\n onSubmit: (\n values: SignInFormValues,\n step: 'identifier' | 'password',\n ) => Promise<void> | void;\n isLoading?: boolean;\n identifier?: string;\n step?: 'identifier' | 'password';\n onBack?: () => void;\n};\n\nexport const SignIn = ({\n onSubmit,\n isLoading = false,\n identifier = '',\n step = 'identifier',\n onBack: _onBack,\n}: SignInProps) => {\n const t = useTranslations('Auth.signIn');\n const [showPassword, setShowPassword] = useState(false);\n\n const identifierSchema = useMemo(\n () =>\n z.object({\n account: z\n .string()\n .min(1, t('errors.accountRequired'))\n .email(t('errors.invalidEmail')),\n }),\n [t],\n );\n\n const passwordSchema = useMemo(\n () =>\n z.object({\n password: z\n .string()\n .min(8, t('errors.passwordLength'))\n .max(128, t('errors.longPasswordError')),\n }),\n [t],\n );\n\n const identifierForm = useForm<{ account: string }>({\n resolver: zodResolver(identifierSchema),\n defaultValues: {\n account: identifier,\n },\n });\n\n const passwordForm = useForm<{ password: string }>({\n resolver: zodResolver(passwordSchema),\n defaultValues: {\n password: '',\n },\n });\n\n const handleIdentifierSubmit = identifierForm.handleSubmit(async (values) => {\n await onSubmit({ account: values.account, password: '' }, 'identifier');\n });\n\n const handlePasswordSubmit = passwordForm.handleSubmit(async (values) => {\n await onSubmit(\n { account: identifier, password: values.password },\n 'password',\n );\n });\n\n if (step === 'password') {\n return (\n <Form {...passwordForm}>\n <form onSubmit={handlePasswordSubmit} className=\"space-y-4\">\n <div className=\"text-center\">\n <p className=\"text-sm text-muted-foreground mb-2\">\n {t('form.enterPasswordFor')}\n </p>\n <p className=\"font-bold\">{identifier}</p>\n </div>\n <FormField\n control={passwordForm.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 <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\n return (\n <Form {...identifierForm}>\n <form onSubmit={handleIdentifierSubmit} className=\"space-y-4\">\n <FormField\n control={identifierForm.control}\n name=\"account\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.accountLabel')}</FormLabel>\n <FormControl>\n <Input\n type=\"text\"\n placeholder={t('form.accountPlaceholder')}\n {...field}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <Button type=\"submit\" className=\"w-full\" disabled={isLoading}>\n {isLoading ? t('form.submitting') : t('form.continue')}\n </Button>\n </form>\n </Form>\n );\n};\n"],"mappings":"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","names":["useTranslations","useState","jsx","useState","jsx","jsxs","jsx","jsxs","useTranslations","useState"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
|
|
4
|
+
type SignUpPageProps = {
|
|
5
|
+
locale?: string;
|
|
6
|
+
onNavigate: (path: string) => void;
|
|
7
|
+
linkComponent?: React.ComponentType<ComponentProps<'a'> & {
|
|
8
|
+
href: string;
|
|
9
|
+
}>;
|
|
10
|
+
links?: {
|
|
11
|
+
signIn?: string;
|
|
12
|
+
};
|
|
13
|
+
initialIdentifier?: string;
|
|
14
|
+
logoImage?: string;
|
|
15
|
+
};
|
|
16
|
+
declare const SignUpPage: ({ onNavigate, linkComponent: Link, links, initialIdentifier, logoImage, }: SignUpPageProps) => react_jsx_runtime.JSX.Element;
|
|
17
|
+
|
|
18
|
+
export { SignUpPage };
|